@@ -27,28 +27,20 @@ const LAYOUT = {
2727 PREFERRED_CONTENT_WIDTH : 60 ,
2828 CONTENT_PADDING : 4 ,
2929
30- // Height thresholds for showing UI elements
31- MIN_HEIGHT_FOR_LOGO : 14 ,
32- MIN_HEIGHT_FOR_HELP_TEXT : 18 ,
33- MIN_HEIGHT_FOR_RECENTS : 10 ,
30+ // Essential element heights (always shown)
31+ INPUT_HEIGHT : 1 ,
32+ BOTTOM_BAR_HEIGHT : 2 ,
33+ MIN_LIST_HEIGHT : 2 , // Minimum rows to show in file picker
34+ MAX_LIST_HEIGHT : 12 ,
3435
35- // Thresholds for number of recent projects to show
36- HEIGHT_FOR_3_RECENTS : 16 ,
37- HEIGHT_FOR_2_RECENTS : 12 ,
36+ // Compact mode threshold - below this, remove padding/margins
37+ COMPACT_MODE_THRESHOLD : 12 ,
3838
39- // Approximate heights of UI elements (in rows)
40- BASE_HEIGHT : 10 , // input (~3) + bottom bar (~3) + padding (~4)
39+ // Decorative element heights
4140 LOGO_HEIGHT : 8 ,
4241 HELP_TEXT_HEIGHT : 2 ,
4342
44- // Directory list constraints
45- MIN_LIST_HEIGHT : 4 ,
46- MAX_LIST_HEIGHT : 12 ,
47-
48- // Bottom bar height (border + content)
49- BOTTOM_BAR_HEIGHT : 2 ,
50-
51- // Spacing constants
43+ // Spacing constants (used in normal mode)
5244 MAIN_CONTENT_PADDING : 2 ,
5345 LOGO_MARGIN_TOP : 1 ,
5446 LOGO_MARGIN_BOTTOM : 1 ,
@@ -114,54 +106,82 @@ export const ProjectPickerScreen: React.FC<ProjectPickerScreenProps> = ({
114106 } , [ ] )
115107
116108 // Use the terminal layout hook for responsive breakpoints
117- const { width, terminalWidth, terminalHeight } = useTerminalLayout ( )
118- const isNarrow = width . is ( 'xs' )
119- const contentMaxWidth = Math . min ( terminalWidth - LAYOUT . CONTENT_PADDING , LAYOUT . MAX_CONTENT_WIDTH )
109+ const { terminalWidth, terminalHeight } = useTerminalLayout ( )
110+ const contentMaxWidth = Math . min (
111+ terminalWidth - LAYOUT . CONTENT_PADDING ,
112+ LAYOUT . MAX_CONTENT_WIDTH ,
113+ )
120114 const contentWidth = Math . min ( LAYOUT . PREFERRED_CONTENT_WIDTH , contentMaxWidth )
121115
122- // Granular responsive breakpoints for showing UI elements
123- const canShowLogo = terminalHeight >= LAYOUT . MIN_HEIGHT_FOR_LOGO
124- const canShowHelpText = terminalHeight >= LAYOUT . MIN_HEIGHT_FOR_HELP_TEXT
125- const canShowRecents = terminalHeight >= LAYOUT . MIN_HEIGHT_FOR_RECENTS && recentProjects . length > 0
126-
127- // Limit number of recent projects based on available height
128- const maxRecentsToShow = terminalHeight >= LAYOUT . HEIGHT_FOR_3_RECENTS ? 3
129- : terminalHeight >= LAYOUT . HEIGHT_FOR_2_RECENTS ? 2
130- : 1
131-
132- // Calculate available height for directory list dynamically
133- const logoHeight = canShowLogo ? LAYOUT . LOGO_HEIGHT : 0
134- const helpTextHeight = canShowHelpText ? LAYOUT . HELP_TEXT_HEIGHT : 0
135- const recentsHeight = canShowRecents ? Math . min ( recentProjects . length , maxRecentsToShow ) + 1 : 0 // +1 for header
136- const fixedElementsHeight = LAYOUT . BASE_HEIGHT + logoHeight + helpTextHeight + recentsHeight
137- const availableListHeight = terminalHeight - fixedElementsHeight
138-
139- // Only show file picker if we have at least MIN_LIST_HEIGHT rows available
140- const canShowFilePicker = availableListHeight >= LAYOUT . MIN_LIST_HEIGHT
141- // Clamp the height between min and max
142- const maxListHeight = canShowFilePicker
143- ? Math . min ( availableListHeight , LAYOUT . MAX_LIST_HEIGHT )
144- : 0
145-
146- // Calculate actual content height to determine if we should center vertically
147- const actualListHeight = canShowFilePicker ? Math . min ( filteredDirectoryItems . length + 2 , maxListHeight + 2 ) : 0 // +2 for border
148- const inputHeight = 3 // input box with border
149- const totalContentHeight =
150- LAYOUT . MAIN_CONTENT_PADDING * 2 + // top and bottom padding
151- logoHeight +
152- ( canShowLogo ? LAYOUT . LOGO_MARGIN_TOP + LAYOUT . LOGO_MARGIN_BOTTOM : 0 ) +
153- helpTextHeight +
154- ( canShowHelpText ? LAYOUT . HELP_TEXT_MARGIN_BOTTOM : 0 ) +
155- inputHeight +
156- actualListHeight +
157- recentsHeight +
158- ( canShowRecents ? LAYOUT . RECENTS_MARGIN_TOP : 0 )
159-
160- // Available space for content (total height minus bottom bar)
161- const availableContentHeight = terminalHeight - LAYOUT . BOTTOM_BAR_HEIGHT
162-
163- // Center content when it doesn't fill the available space
164- const shouldCenterContent = totalContentHeight < availableContentHeight
116+ // Compact mode: remove padding/margins when space is tight
117+ const isCompactMode = terminalHeight < LAYOUT . COMPACT_MODE_THRESHOLD
118+ const mainPadding = isCompactMode ? 0 : LAYOUT . MAIN_CONTENT_PADDING
119+
120+ // Calculate essential height first (these always show)
121+ // Essential = input (1) + file picker border (2) + bottom bar (2) + minimal padding
122+ const essentialHeight =
123+ LAYOUT . INPUT_HEIGHT + 2 + LAYOUT . BOTTOM_BAR_HEIGHT + ( isCompactMode ? 0 : 2 )
124+
125+ // Calculate remaining height for file picker and optional elements
126+ const remainingHeight = terminalHeight - essentialHeight
127+
128+ // File picker gets priority - calculate how much space it needs
129+ const filePickerHeight = Math . max (
130+ LAYOUT . MIN_LIST_HEIGHT ,
131+ Math . min ( remainingHeight , LAYOUT . MAX_LIST_HEIGHT ) ,
132+ )
133+
134+ // After file picker, calculate space for optional elements
135+ const spaceAfterFilePicker = remainingHeight - filePickerHeight
136+
137+ // Determine which optional elements can fit (priority: recents first, then logo, then help text)
138+ const logoHeightNeeded =
139+ LAYOUT . LOGO_HEIGHT +
140+ ( isCompactMode ? 0 : LAYOUT . LOGO_MARGIN_TOP + LAYOUT . LOGO_MARGIN_BOTTOM )
141+ const helpTextHeightNeeded =
142+ LAYOUT . HELP_TEXT_HEIGHT +
143+ ( isCompactMode ? 0 : LAYOUT . HELP_TEXT_MARGIN_BOTTOM )
144+
145+ // Allocate space for optional elements based on available space
146+ let availableForOptional = spaceAfterFilePicker
147+
148+ // Try to fit recents first (most useful)
149+ let recentsToShow = 0
150+ if ( recentProjects . length > 0 && availableForOptional >= 2 ) {
151+ // Calculate how many recents fit
152+ const baseRecentsHeight =
153+ 1 + ( isCompactMode ? 0 : LAYOUT . RECENTS_MARGIN_TOP ) // header + margin
154+ const remainingForRecents = availableForOptional - baseRecentsHeight
155+ recentsToShow = Math . min (
156+ recentProjects . length ,
157+ Math . max ( 0 , remainingForRecents ) ,
158+ 3 ,
159+ )
160+ if ( recentsToShow > 0 ) {
161+ availableForOptional -=
162+ recentsToShow + 1 + ( isCompactMode ? 0 : LAYOUT . RECENTS_MARGIN_TOP )
163+ }
164+ }
165+
166+ // Try to fit logo (decorative but nice)
167+ const canShowLogo = ! isCompactMode && availableForOptional >= logoHeightNeeded
168+ if ( canShowLogo ) {
169+ availableForOptional -= logoHeightNeeded
170+ }
171+
172+ // Try to fit help text (least important)
173+ const canShowHelpText =
174+ ! isCompactMode && availableForOptional >= helpTextHeightNeeded
175+
176+ const canShowRecents = recentsToShow > 0
177+ const maxRecentsToShow = recentsToShow
178+
179+ // File picker is always shown if there's any space
180+ const canShowFilePicker = remainingHeight >= LAYOUT . MIN_LIST_HEIGHT
181+ const maxListHeight = filePickerHeight
182+
183+ // Center content only in non-compact mode when there's extra space
184+ const shouldCenterContent = ! isCompactMode && spaceAfterFilePicker > 10
165185
166186 // Logo setup
167187 const blockColor = getLogoBlockColor ( theme . name )
@@ -284,21 +304,21 @@ export const ProjectPickerScreen: React.FC<ProjectPickerScreenProps> = ({
284304 alignItems : 'center' ,
285305 justifyContent : shouldCenterContent ? 'center' : 'flex-start' ,
286306 width : '100%' ,
287- padding : LAYOUT . MAIN_CONTENT_PADDING ,
288- gap : 1 ,
307+ padding : mainPadding ,
308+ gap : isCompactMode ? 0 : 1 ,
289309 flexGrow : 1 ,
290310 flexShrink : 1 ,
291311 } }
292312 >
293- { /* Logo - show when terminal height >= 14 */ }
313+ { /* Logo - show when there's enough space after essentials */ }
294314 { canShowLogo && (
295315 < box
296316 style = { {
297317 flexDirection : 'column' ,
298318 alignItems : 'center' ,
299319 width : '100%' ,
300- marginTop : LAYOUT . LOGO_MARGIN_TOP ,
301- marginBottom : LAYOUT . LOGO_MARGIN_BOTTOM ,
320+ marginTop : isCompactMode ? 0 : LAYOUT . LOGO_MARGIN_TOP ,
321+ marginBottom : isCompactMode ? 0 : LAYOUT . LOGO_MARGIN_BOTTOM ,
302322 flexShrink : 0 ,
303323 } }
304324 >
@@ -308,14 +328,14 @@ export const ProjectPickerScreen: React.FC<ProjectPickerScreenProps> = ({
308328 </ box >
309329 ) }
310330
311- { /* Help text - show when terminal height >= 18 */ }
331+ { /* Help text - show only when there's plenty of space */ }
312332 { canShowHelpText && (
313333 < box
314334 style = { {
315335 flexDirection : 'column' ,
316336 alignItems : 'center' ,
317337 maxWidth : contentMaxWidth ,
318- marginBottom : LAYOUT . HELP_TEXT_MARGIN_BOTTOM ,
338+ marginBottom : isCompactMode ? 0 : LAYOUT . HELP_TEXT_MARGIN_BOTTOM ,
319339 flexShrink : 0 ,
320340 } }
321341 >
@@ -339,7 +359,7 @@ export const ProjectPickerScreen: React.FC<ProjectPickerScreenProps> = ({
339359 onSubmit = { ( ) => { } } // Enter key handled by onKeyIntercept
340360 onPaste = { ( ) => { } } // Paste not needed for path input
341361 onKeyIntercept = { handleSearchKeyIntercept }
342- placeholder = "Type path or filter (Tab to complete) ..."
362+ placeholder = "Select project directory ..."
343363 focused = { true }
344364 maxHeight = { 1 }
345365 minHeight = { 1 }
@@ -372,13 +392,13 @@ export const ProjectPickerScreen: React.FC<ProjectPickerScreenProps> = ({
372392 </ box >
373393 ) }
374394
375- { /* Recent Projects - show when terminal height >= 10 */ }
395+ { /* Recent Projects - show when there's space after file picker */ }
376396 { canShowRecents && (
377397 < box
378398 style = { {
379399 flexDirection : 'column' ,
380400 width : contentWidth ,
381- marginTop : LAYOUT . RECENTS_MARGIN_TOP ,
401+ marginTop : isCompactMode ? 0 : LAYOUT . RECENTS_MARGIN_TOP ,
382402 flexShrink : 0 ,
383403 gap : 0 ,
384404 } }
@@ -390,7 +410,7 @@ export const ProjectPickerScreen: React.FC<ProjectPickerScreenProps> = ({
390410 style = { {
391411 flexDirection : 'row' ,
392412 gap : 1 ,
393- paddingLeft : LAYOUT . RECENTS_PADDING_LEFT ,
413+ paddingLeft : isCompactMode ? 0 : LAYOUT . RECENTS_PADDING_LEFT ,
394414 height : 1 ,
395415 } }
396416 >
@@ -405,7 +425,6 @@ export const ProjectPickerScreen: React.FC<ProjectPickerScreenProps> = ({
405425 ) ) }
406426 </ box >
407427 ) }
408-
409428 </ box >
410429
411430 { /* Bottom bar - fixed at bottom with Open button */ }
@@ -434,9 +453,7 @@ export const ProjectPickerScreen: React.FC<ProjectPickerScreenProps> = ({
434453 >
435454 { /* Current directory path */ }
436455 < box style = { { flexGrow : 1 , flexShrink : 1 , overflow : 'hidden' } } >
437- < text style = { { fg : theme . muted } } >
438- { formatCwd ( currentPath ) }
439- </ text >
456+ < text style = { { fg : theme . muted } } > { formatCwd ( currentPath ) } </ text >
440457 </ box >
441458
442459 { /* Open button */ }
0 commit comments