()
| 34 | |
| 35 | /** Help banner showing keyboard shortcuts and tips in an organized layout. */ |
| 36 | export const HelpBanner = () => { |
| 37 | const setInputMode = useChatStore((state) => state.setInputMode) |
| 38 | const theme = useTheme() |
| 39 | const { data: subscriptionData } = useSubscriptionQuery() |
| 40 | const hasSubscription = subscriptionData?.hasSubscription ?? false |
| 41 | const chatGptOAuth = getChatGptOAuthStatus() |
| 42 | |
| 43 | // Auto-hide after timeout |
| 44 | React.useEffect(() => { |
| 45 | const timer = setTimeout(() => { |
| 46 | setInputMode('default') |
| 47 | }, HELP_TIMEOUT) |
| 48 | return () => clearTimeout(timer) |
| 49 | }, [setInputMode]) |
| 50 | |
| 51 | return ( |
| 52 | <BottomBanner |
| 53 | borderColorKey="info" |
| 54 | onClose={() => setInputMode('default')} |
| 55 | > |
| 56 | <box style={{ flexDirection: 'column', gap: 1, flexGrow: 1 }}> |
| 57 | {/* Shortcuts Section */} |
| 58 | <box style={{ flexDirection: 'column', gap: 0 }}> |
| 59 | <SectionHeader>Shortcuts</SectionHeader> |
| 60 | <box style={{ flexDirection: 'row', flexWrap: 'wrap', columnGap: 2, paddingLeft: 2 }}> |
| 61 | <Shortcut keys="Ctrl+C / Esc" action="stop" /> |
| 62 | <Shortcut keys="Ctrl+J / Opt+Enter" action="newline" /> |
| 63 | <Shortcut keys="↑↓" action="history" /> |
| 64 | <Shortcut keys="Ctrl+T" action="collapse/expand agents" /> |
| 65 | </box> |
| 66 | </box> |
| 67 | |
| 68 | {/* Features Section */} |
| 69 | <box style={{ flexDirection: 'column', gap: 0 }}> |
| 70 | <SectionHeader>Features</SectionHeader> |
| 71 | <box style={{ flexDirection: 'row', flexWrap: 'wrap', columnGap: 2, paddingLeft: 2 }}> |
| 72 | <Shortcut keys="/" action="commands" /> |
| 73 | <Shortcut keys="@files" action="mention" /> |
| 74 | <Shortcut keys="@agents" action="use agent" /> |
| 75 | <Shortcut keys="!bash" action="run command" /> |
| 76 | </box> |
| 77 | </box> |
| 78 | |
| 79 | {/* Tips Section */} |
| 80 | <box style={{ flexDirection: 'column', gap: 0 }}> |
| 81 | <SectionHeader>Tips</SectionHeader> |
| 82 | <box style={{ flexDirection: 'column', paddingLeft: 2 }}> |
| 83 | {IS_FREEBUFF && !chatGptOAuth.connected && ( |
| 84 | <text style={{ fg: theme.muted }}> |
| 85 | Connect via /connect to unlock /plan & /review |
| 86 | </text> |
| 87 | )} |
| 88 | {IS_FREEBUFF && chatGptOAuth.connected && ( |
| 89 | <text style={{ fg: theme.muted }}> |
| 90 | Try workflow: /interview → /plan → implement → /review |
| 91 | </text> |
| 92 | )} |
| 93 | <text style={{ fg: theme.muted }}> |
nothing calls this directly
no test coverage detected