@@ -6,6 +6,7 @@ import (
66 "github.com/charmbracelet/bubbles/v2/key"
77 tea "github.com/charmbracelet/bubbletea/v2"
88 "github.com/opencode-ai/opencode/internal/app"
9+ "github.com/opencode-ai/opencode/internal/logging"
910 "github.com/opencode-ai/opencode/internal/message"
1011 "github.com/opencode-ai/opencode/internal/session"
1112 "github.com/opencode-ai/opencode/internal/tui/components/chat"
@@ -19,32 +20,28 @@ import (
1920
2021var ChatPage page.PageID = "chat"
2122
23+type ChatFocusedMsg struct {
24+ Focused bool // True if the chat input is focused, false otherwise
25+}
26+
2227type chatPage struct {
2328 app *app.App
2429
2530 layout layout.SplitPaneLayout
2631
2732 session session.Session
28−}
2933
30−type ChatKeyMap struct {
31− NewSession key.Binding
32− Cancel key.Binding
33−}
34+ keyMap KeyMap
3435
35−var keyMap = ChatKeyMap{
36− NewSession: key.NewBinding(
37− key.WithKeys("ctrl+n"),
38− key.WithHelp("ctrl+n", "new session"),
39− ),
40− Cancel: key.NewBinding(
41− key.WithKeys("esc"),
42− key.WithHelp("esc", "cancel"),
43− ),
36+ chatFocused bool
4437}
4538
4639func (p *chatPage) Init() tea.Cmd {
47− return p.layout.Init()
40+ cmd := p.layout.Init()
41+ return tea.Batch(
42+ cmd,
43+ p.layout.FocusPanel(layout.BottomPanel), // Focus on the bottom panel (editor)
44+ )
4845}
4946
5047func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
@@ -79,13 +76,28 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
7976 p.session = msg
8077 case tea.KeyPressMsg:
8178 switch {
82− case key.Matches(msg, keyMap.NewSession):
79+ case key.Matches(msg, p.keyMap.NewSession):
8380 p.session = session.Session{}
8481 return p, tea.Batch(
8582 p.clearMessages(),
8683 util.CmdHandler(chat.SessionClearedMsg{}),
8784 )
88− case key.Matches(msg, keyMap.Cancel):
85+
86+ case key.Matches(msg, p.keyMap.Tab):
87+ logging.Info("Tab key pressed, toggling chat focus")
88+ if p.session.ID == "" {
89+ return p, nil
90+ }
91+ p.chatFocused = !p.chatFocused
92+ if p.chatFocused {
93+ cmds = append(cmds, p.layout.FocusPanel(layout.LeftPanel))
94+ cmds = append(cmds, util.CmdHandler(ChatFocusedMsg{Focused: true}))
95+ } else {
96+ cmds = append(cmds, p.layout.FocusPanel(layout.BottomPanel))
97+ cmds = append(cmds, util.CmdHandler(ChatFocusedMsg{Focused: false}))
98+ }
99+ return p, tea.Batch(cmds...)
100+ case key.Matches(msg, p.keyMap.Cancel):
89101 if p.session.ID != "" {
90102 // Cancel the current session's generation process
91103 // This allows users to interrupt long-running operations
@@ -148,11 +160,6 @@ func (p *chatPage) View() tea.View {
148160 return p.layout.View()
149161}
150162
151−func (p *chatPage) BindingKeys() []key.Binding {
152− bindings := layout.KeyMapToSlice(keyMap)
153− return bindings
154−}
155−
156163func NewChatPage(app *app.App) util.Model {
157164 sidebarContainer := layout.NewContainer(
158165 sidebar.NewSidebarCmp(),
@@ -169,5 +176,6 @@ func NewChatPage(app *app.App) util.Model {
169176 layout.WithFixedBottomHeight(5),
170177 layout.WithFixedRightWidth(31),
171178 ),
179+ keyMap: DefaultKeyMap(),
172180 }
173181}