@@ -35,6 +35,14 @@ type FileHistory struct {
36const LogoHeightBreakpoint = 40
36const LogoHeightBreakpoint = 40
38+// Default maximum number of items to show in each section
40+ DefaultMaxFilesShown = 10
41+ DefaultMaxLSPsShown = 8
42+ DefaultMaxMCPsShown = 8
43+ MinItemsPerSection = 2 // Minimum items to show per section
38type SessionFile struct {
46type SessionFile struct {
39 History FileHistory
47 History FileHistory
40 FilePath string
48 FilePath string
@@ -266,6 +274,79 @@ func (m *sidebarCmp) getMaxWidth() int {
266 return min(m.width-2, 58) // -2 for padding
274 return min(m.width-2, 58) // -2 for padding
277+// calculateAvailableHeight estimates how much height is available for dynamic content
278+func (m *sidebarCmp) calculateAvailableHeight() int {
282+ if m.height > LogoHeightBreakpoint {
283+ usedHeight += 7 // Approximate logo height
285+ usedHeight += 2 // Smaller logo height
287+ usedHeight += 1 // Empty line after logo
290+ if m.session.ID != "" {
291+ usedHeight += 1 // Title line
292+ usedHeight += 1 // Empty line after title
296+ usedHeight += 1 // CWD line
297+ usedHeight += 1 // Empty line after CWD
300+ usedHeight += 2 // Model info
302+ usedHeight += 6 // 3 sections × 2 lines each (header + empty line)
305+ usedHeight += 2 // Top and bottom padding
307+ return max(0, m.height-usedHeight)
310+// getDynamicLimits calculates how many items to show in each section based on available height
311+func (m *sidebarCmp) getDynamicLimits() (maxFiles, maxLSPs, maxMCPs int) {
312+ availableHeight := m.calculateAvailableHeight()
314+ // If we have very little space, use minimum values
315+ if availableHeight < 10 {
316+ return MinItemsPerSection, MinItemsPerSection, MinItemsPerSection
319+ // Distribute available height among the three sections
320+ // Give priority to files, then LSPs, then MCPs
322+ heightPerSection := availableHeight / totalSections
324+ // Calculate limits for each section, ensuring minimums
325+ maxFiles = max(MinItemsPerSection, min(DefaultMaxFilesShown, heightPerSection))
326+ maxLSPs = max(MinItemsPerSection, min(DefaultMaxLSPsShown, heightPerSection))
327+ maxMCPs = max(MinItemsPerSection, min(DefaultMaxMCPsShown, heightPerSection))
329+ // If we have extra space, give it to files first
330+ remainingHeight := availableHeight - (maxFiles + maxLSPs + maxMCPs)
331+ if remainingHeight > 0 {
332+ extraForFiles := min(remainingHeight, DefaultMaxFilesShown-maxFiles)
333+ maxFiles += extraForFiles
334+ remainingHeight -= extraForFiles
336+ if remainingHeight > 0 {
337+ extraForLSPs := min(remainingHeight, DefaultMaxLSPsShown-maxLSPs)
338+ maxLSPs += extraForLSPs
339+ remainingHeight -= extraForLSPs
341+ if remainingHeight > 0 {
342+ maxMCPs += min(remainingHeight, DefaultMaxMCPsShown-maxMCPs)
347+ return maxFiles, maxLSPs, maxMCPs
269func (m *sidebarCmp) filesBlock() string {
350func (m *sidebarCmp) filesBlock() string {
270 t := styles.CurrentTheme()
351 t := styles.CurrentTheme()
@@ -294,10 +375,19 @@ func (m *sidebarCmp) filesBlock() string {
294 return files[i].History.latestVersion.CreatedAt > files[j].History.latestVersion.CreatedAt
375 return files[i].History.latestVersion.CreatedAt > files[j].History.latestVersion.CreatedAt
378+ // Limit the number of files shown
379+ maxFiles, _, _ := m.getDynamicLimits()
380+ maxFiles = min(len(files), maxFiles)
297 for _, file := range files {
383 for _, file := range files {
298 if file.Additions == 0 && file.Deletions == 0 {
384 if file.Additions == 0 && file.Deletions == 0 {
299 continue // skip files with no changes
385 continue // skip files with no changes
387+ if filesShown >= maxFiles {
301 var statusParts []string
391 var statusParts []string
302 if file.Additions > 0 {
392 if file.Additions > 0 {
303 statusParts = append(statusParts, t.S().Base.Foreground(t.Success).Render(fmt.Sprintf("+%d", file.Additions)))
393 statusParts = append(statusParts, t.S().Base.Foreground(t.Success).Render(fmt.Sprintf("+%d", file.Additions)))
@@ -323,6 +413,21 @@ func (m *sidebarCmp) filesBlock() string {
323 m.getMaxWidth(),
413 m.getMaxWidth(),
419+ // Add indicator if there are more files
420+ totalFilesWithChanges := 0
421+ for _, file := range files {
422+ if file.Additions > 0 || file.Deletions > 0 {
423+ totalFilesWithChanges++
426+ if totalFilesWithChanges > maxFiles {
427+ remaining := totalFilesWithChanges - maxFiles
428+ fileList = append(fileList,
429+ t.S().Base.Foreground(t.FgMuted).Render(fmt.Sprintf("… and %d more", remaining)),
328 return lipgloss.JoinVertical(
433 return lipgloss.JoinVertical(
@@ -350,7 +455,14 @@ func (m *sidebarCmp) lspBlock() string {
458+ // Limit the number of LSPs shown
459+ _, maxLSPs, _ := m.getDynamicLimits()
460+ maxLSPs = min(len(lsp), maxLSPs)
353− for _, l := range lsp {
461+ for i, l := range lsp {
354 iconColor := t.Success
466 iconColor := t.Success
355 if l.LSP.Disabled {
467 if l.LSP.Disabled {
356 iconColor = t.FgMuted
468 iconColor = t.FgMuted
@@ -398,6 +510,14 @@ func (m *sidebarCmp) lspBlock() string {
513+ // Add indicator if there are more LSPs
514+ if len(lsp) > maxLSPs {
515+ remaining := len(lsp) - maxLSPs
516+ lspList = append(lspList,
517+ t.S().Base.Foreground(t.FgMuted).Render(fmt.Sprintf("… and %d more", remaining)),
401 return lipgloss.JoinVertical(
521 return lipgloss.JoinVertical(
402 lipgloss.Left,
522 lipgloss.Left,
403 lspList...,
523 lspList...,
@@ -423,7 +543,14 @@ func (m *sidebarCmp) mcpBlock() string {
546+ // Limit the number of MCPs shown
547+ _, _, maxMCPs := m.getDynamicLimits()
548+ maxMCPs = min(len(mcps), maxMCPs)
426− for _, l := range mcps {
549+ for i, l := range mcps {
427 iconColor := t.Success
554 iconColor := t.Success
428 if l.MCP.Disabled {
555 if l.MCP.Disabled {
429 iconColor = t.FgMuted
556 iconColor = t.FgMuted
@@ -440,6 +567,14 @@ func (m *sidebarCmp) mcpBlock() string {
570+ // Add indicator if there are more MCPs
571+ if len(mcps) > maxMCPs {
572+ remaining := len(mcps) - maxMCPs
573+ mcpList = append(mcpList,
574+ t.S().Base.Foreground(t.FgMuted).Render(fmt.Sprintf("… and %d more", remaining)),
443 return lipgloss.JoinVertical(
578 return lipgloss.JoinVertical(
444 lipgloss.Left,
579 lipgloss.Left,
445 mcpList...,
580 mcpList...,