@@ -12,20 +12,7 @@ pub fn render_modal(app: &App, frame: &mut Frame, area: Rect) {
1212 return ;
1313 }
1414
15- // Create modal area (centered)
16- let modal_width = ( area. width * 3 ) / 4 ;
17- let modal_height = ( area. height * 3 ) / 4 ;
18- let modal_x = ( area. width - modal_width) / 2 ;
19- let modal_y = ( area. height - modal_height) / 2 ;
20-
21- let modal_area = Rect :: new (
22- area. x + modal_x,
23- area. y + modal_y,
24- modal_width,
25- modal_height,
26- ) ;
27-
28- // Create modal content based on type
15+ // Calculate content to determine optimal modal size
2916 let ( title, content) = match & app. modal_data {
3017 ModalData :: ProcessDetails { name, pid, cpu_usage, memory_usage, status, cmd } => {
3118 let title = format ! ( "Process Details: {}" , name) ;
@@ -111,6 +98,32 @@ pub fn render_modal(app: &App, frame: &mut Frame, area: Rect) {
11198 }
11299 } ;
113100
101+ // Calculate optimal modal size based on content
102+ let content_lines = content. lines ( ) . count ( ) + 3 ; // +3 for title, spacing, and close button
103+ let max_line_width = content. lines ( ) . map ( |line| line. len ( ) ) . max ( ) . unwrap_or ( 20 ) ;
104+
105+ let modal_width = std:: cmp:: min (
106+ std:: cmp:: max ( max_line_width as u16 + 4 , 40 ) , // Minimum 40, content width + padding
107+ area. width . saturating_sub ( 8 ) // Leave some margin from screen edges
108+ ) ;
109+ let modal_height = std:: cmp:: min (
110+ std:: cmp:: max ( content_lines as u16 + 2 , 8 ) , // Minimum 8, content height + padding
111+ area. height . saturating_sub ( 6 ) // Leave some margin from screen edges
112+ ) ;
113+
114+ // Center the modal
115+ let modal_x = ( area. width - modal_width) / 2 ;
116+ let modal_y = ( area. height - modal_height) / 2 ;
117+
118+ let modal_area = Rect :: new (
119+ area. x + modal_x,
120+ area. y + modal_y,
121+ modal_width,
122+ modal_height,
123+ ) ;
124+
125+ // Content already calculated above, now render the modal
126+
114127 // Clear the modal area first to ensure no background interference
115128 frame. render_widget ( Clear , modal_area) ;
116129
@@ -119,12 +132,12 @@ pub fn render_modal(app: &App, frame: &mut Frame, area: Rect) {
119132 . style ( Style :: default ( ) . bg ( Color :: Black ) ) ;
120133 frame. render_widget ( solid_background, modal_area) ;
121134
122- // Create content area inside the modal (full height minus borders )
135+ // Create content area inside the modal (leave space for close button )
123136 let content_area = Rect :: new (
124137 modal_area. x + 1 ,
125138 modal_area. y + 1 ,
126139 modal_area. width - 2 ,
127- modal_area. height - 2 , // Full height minus borders
140+ modal_area. height - 4 , // Leave space for close button
128141 ) ;
129142
130143 // Render modal content with solid black background
@@ -136,6 +149,26 @@ pub fn render_modal(app: &App, frame: &mut Frame, area: Rect) {
136149
137150 frame. render_widget ( modal_content, content_area) ;
138151
152+ // Render close button at the bottom
153+ let button_area = Rect :: new (
154+ modal_area. x + 1 ,
155+ modal_area. y + modal_area. height - 3 ,
156+ modal_area. width - 2 ,
157+ 1 ,
158+ ) ;
159+
160+ let close_button = Paragraph :: new ( "[ Close ]" )
161+ . style ( Style :: default ( )
162+ . fg ( Color :: Black )
163+ . bg ( Color :: Yellow ) ) // Highlighted button
164+ . alignment ( Alignment :: Center )
165+ . block ( Block :: default ( )
166+ . style ( Style :: default ( )
167+ . fg ( Color :: Black )
168+ . bg ( Color :: Yellow ) ) ) ;
169+
170+ frame. render_widget ( close_button, button_area) ;
171+
139172 // Render the modal border on top with title
140173 let modal_block = Block :: default ( )
141174 . title ( title)
0 commit comments