feat(cli): keybinding system — Ctrl+L sidebar, Ctrl+N new, Ctrl+K search (TUI-009)

This commit is contained in:
2026-03-15 15:05:00 -05:00
parent 9ef578c20d
commit 9f38f5ab31
2 changed files with 36 additions and 6 deletions

View File

@@ -57,9 +57,26 @@ export function TuiApp({ gatewayUrl, conversationId, sessionCookie }: TuiAppProp
if (key.ctrl && ch === 'c') {
exit();
}
// Ctrl+B: toggle sidebar
if (key.ctrl && ch === 'b') {
// Ctrl+L: toggle sidebar (refresh on open)
if (key.ctrl && ch === 'l') {
const willOpen = !appMode.sidebarOpen;
appMode.toggleSidebar();
if (willOpen) {
void conversations.refresh();
}
}
// Ctrl+N: create new conversation and switch to it
if (key.ctrl && ch === 'n') {
void conversations.createConversation().then((conv) => {
if (conv) {
socket.switchConversation(conv.id);
appMode.setMode('chat');
}
});
}
// Ctrl+K: toggle search mode
if (key.ctrl && ch === 'k') {
appMode.setMode(appMode.mode === 'search' ? 'chat' : 'search');
}
// Page Up / Page Down: scroll message history (only in chat mode)
if (appMode.mode === 'chat') {
@@ -82,14 +99,22 @@ export function TuiApp({ gatewayUrl, conversationId, sessionCookie }: TuiAppProp
}
}
}
// Escape: return to chat from sidebar
if (key.escape && appMode.mode === 'sidebar') {
// Escape: return to chat from sidebar/search; in chat, scroll to bottom
if (key.escape) {
if (appMode.mode === 'sidebar' || appMode.mode === 'search') {
appMode.setMode('chat');
} else if (appMode.mode === 'chat') {
viewport.scrollToBottom();
}
}
});
const inputPlaceholder =
appMode.mode !== 'chat' ? 'focus is on sidebar… press Esc to return' : undefined;
appMode.mode === 'sidebar'
? 'focus is on sidebar… press Esc to return'
: appMode.mode === 'search'
? 'search mode… press Esc to return'
: undefined;
const messageArea = (
<Box flexDirection="column" flexGrow={1}>

View File

@@ -46,6 +46,11 @@ export function BottomBar({
return (
<Box flexDirection="column" paddingX={0} marginTop={0}>
{/* Line 0: keybinding hints */}
<Box>
<Text dimColor>^L sidebar · ^N new · ^K search · ^T thinking · PgUp/Dn scroll</Text>
</Box>
{/* Line 1: blank ····· Gateway: Status */}
<Box justifyContent="space-between">
<Box />