Skip to content

Commit e4197c2

Browse files
seanb4tclaude
andcommitted
fix(tui): skip preview pane in tab cycle when no email is selected
Tab previously cycled through all three panes (Mailbox → EmailList → Preview) even when the preview was empty, requiring two Tab presses to reach mailboxes from the email list. Now the preview pane is excluded from the cycle until an email is actually selected. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4b2cbfb commit e4197c2

9 files changed

Lines changed: 82 additions & 62 deletions

internal/tui/layout.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ type paneLayout struct {
3434

3535
// paneManager tracks focus, sidebar visibility, and split ratio.
3636
type paneManager struct {
37-
focus PaneID
38-
sidebar bool
39-
splitPct int // percentage of main area for email list (30-80)
37+
focus PaneID
38+
sidebar bool
39+
hasPreview bool // true when an email is selected and preview pane has content
40+
splitPct int // percentage of main area for email list (30-80)
4041
}
4142

4243
func newPaneManager() paneManager {
@@ -59,10 +60,15 @@ func (pm *paneManager) cycleFocus() {
5960
}
6061

6162
func (pm *paneManager) visiblePanes() []PaneID {
63+
var panes []PaneID
6264
if pm.sidebar {
63-
return []PaneID{PaneMailbox, PaneEmailList, PanePreview}
65+
panes = append(panes, PaneMailbox)
6466
}
65-
return []PaneID{PaneEmailList, PanePreview}
67+
panes = append(panes, PaneEmailList)
68+
if pm.hasPreview {
69+
panes = append(panes, PanePreview)
70+
}
71+
return panes
6672
}
6773

6874
func (pm *paneManager) toggleSidebar() {

internal/tui/layout_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ func TestNewPaneManager(t *testing.T) {
2222

2323
func TestPaneManager_CycleFocus(t *testing.T) {
2424
pm := newPaneManager()
25+
pm.hasPreview = true
2526
pm.focus = PaneMailbox
2627

2728
pm.cycleFocus()
@@ -34,9 +35,21 @@ func TestPaneManager_CycleFocus(t *testing.T) {
3435
assert.Equal(t, PaneMailbox, pm.focus)
3536
}
3637

38+
func TestPaneManager_CycleFocus_SkipsPreviewWhenEmpty(t *testing.T) {
39+
pm := newPaneManager()
40+
pm.focus = PaneMailbox
41+
42+
pm.cycleFocus()
43+
assert.Equal(t, PaneEmailList, pm.focus)
44+
45+
pm.cycleFocus()
46+
assert.Equal(t, PaneMailbox, pm.focus, "should wrap back to mailbox, skipping empty preview")
47+
}
48+
3749
func TestPaneManager_CycleFocus_SkipsSidebarWhenHidden(t *testing.T) {
3850
pm := newPaneManager()
3951
pm.sidebar = false
52+
pm.hasPreview = true
4053
pm.focus = PaneEmailList
4154

4255
pm.cycleFocus()

internal/tui/testdata/TestIntegration_DashboardLoad.golden

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
│ 5 items ││ 5 items │
66
│ ││ │
77
││ Inbox (3) │││ * — Weekly Team Standup Notes │
8-
││ 25 emails │││ 7h ago Here are the notes from today's standup. Backend team completed the API migrati… │
8+
││ 25 emails │││ 8h ago Here are the notes from today's standup. Backend team completed the API migrati… │
99
│ ││ │
1010
│ Drafts ││ ! — Project Deadline Update │
11-
│ 2 emails ││ 8h ago The deadline for Phase 2 has been moved to March 15th. Please update your proje… │
11+
│ 2 emails ││ 9h ago The deadline for Phase 2 has been moved to March 15th. Please update your proje… │
1212
│ ││ │
1313
│ Sent ││ — Invoice #2847 Attached │
1414
│ 150 emails ││ 1d ago Please find attached the invoice for services rendered in January 2026. Payment… │

internal/tui/testdata/TestIntegration_NarrowTerminal.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
│ 5 items │
66
│ │
77
││ * — Weekly Team Standup Notes │
8-
││ 7h ago Here are the notes from today's standup. Backen…│
8+
││ 8h ago Here are the notes from today's standup. Backen…│
99
│ ••••• │
1010
│ │
1111
│ ↑/k up • ↓/j down • / filter • q quit • ? more │

internal/tui/testdata/TestIntegration_ReadEmail.golden

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
│ 5 items ││ 5 items │
66
│ ││ │
77
││ Inbox (3) │││ * — Weekly Team Standup Notes │
8-
││ 25 emails │││ 7h ago Here are the notes from today's standup. Backend team completed the API migrati… │
8+
││ 25 emails │││ 8h ago Here are the notes from today's standup. Backend team completed the API migrati… │
99
│ ││ │
1010
│ Drafts ││ ! — Project Deadline Update │
11-
│ 2 emails ││ 8h ago The deadline for Phase 2 has been moved to March 15th. Please update your proje… │
11+
│ 2 emails ││ 9h ago The deadline for Phase 2 has been moved to March 15th. Please update your proje… │
1212
│ ││ │
1313
│ Sent ││ — Invoice #2847 Attached │
1414
│ 150 emails ││ 1d ago Please find attached the invoice for services rendered in January 2026. Payment… │

internal/tui/testdata/TestIntegration_SelectMailbox_Arrows.golden

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
 unread 3 │ flagged 0 │ today 0 Fastmail CLI
22
╭──────────────────╮╭─────────────────────────────────────────────────────────────────────────────────────────────────╮
3-
│ Mailboxes ││ Sent
3+
│ Mailboxes ││ Inbox
44
│ ││ │
55
│ 5 items ││ 5 items │
66
│ ││ │
7-
Inbox (3) ││ * — Weekly Team Standup Notes │
8-
25 emails │││ 7h ago Here are the notes from today's standup. Backend team completed the API migrati… │
7+
Inbox (3) ││ * — Weekly Team Standup Notes │
8+
25 emails ││ 8h ago Here are the notes from today's standup. Backend team completed the API migrati… │
99
│ ││ │
1010
│ Drafts ││ ! — Project Deadline Update │
11-
│ 2 emails ││ 8h ago The deadline for Phase 2 has been moved to March 15th. Please update your proje… │
11+
│ 2 emails ││ 9h ago The deadline for Phase 2 has been moved to March 15th. Please update your proje… │
1212
│ ││ │
13-
Sent ││ — Invoice #2847 Attached │
14-
150 emails ││ 1d ago Please find attached the invoice for services rendered in January 2026. Payment… │
13+
Sent ││ — Invoice #2847 Attached │
14+
150 emails ││ 1d ago Please find attached the invoice for services rendered in January 2026. Payment… │
1515
│ ││ │
1616
│ Archive ││ │
1717
│ 500 emails ││ │
1818
│ ││ •• │
1919
│ Trash ││ │
2020
│ 10 emails ││ ↑/k up • ↓/j down • / filter • q quit • ? more │
21-
│ ││
22-
│ ││
23-
│ ││
24-
│ ││
25-
│ ││
26-
│ ││
27-
│ ││
28-
│ ││
29-
│ ││ │
30-
│ ││
31-
│ ││ │
32-
│ ││
33-
│ ││
34-
│ ││
35-
│ ││ │
36-
│ ││
37-
│ ││
38-
│ ↑/k up • ↓/j ││
21+
│ ││─────────────────────────────────────────────────────────────────────────────────────────────────
22+
│ ││──
23+
│ ││ From: Alice Chen <alice@example.com>
24+
│ ││ To: Test User <test@fastmail.com>
25+
│ ││ Subj: Weekly Team Standup Notes
26+
│ ││ Date: Mon, 09 Feb 2026 10:30 UTC
27+
│ ││ ─────────────────────────────────────────────────────────────────────────────────────────────
28+
│ ││ Hi team,
29+
│ ││ │
30+
│ ││ Here are the notes from today's standup.
31+
│ ││ │
32+
│ ││ Backend team:
33+
│ ││ - Completed the API migration ahead of schedule
34+
│ ││ - Starting work on the caching layer
35+
│ ││ │
36+
│ ││ Frontend team:
37+
│ ││ - On track for the v2.1 release
38+
│ ↑/k up • ↓/j ││ - Fixed 3 accessibility issues
3939
╰──────────────────╯╰─────────────────────────────────────────────────────────────────────────────────────────────────╯
40-
enter open / filter tab pane b sidebar ? help q quit
40+
enter read a archive f flag c compose / search tab pane b sidebar ? help q quit

0 commit comments

Comments
 (0)