Roo-Code/apps/cli/src/ui/hooks/useFocusManagement.ts
Chris Estreich ea9717d7ba
Add a TUI (#10480)
Co-authored-by: Roo Code <roomote@roocode.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com>
Co-authored-by: Daniel <57051444+daniel-lxs@users.noreply.github.com>
2026-01-09 19:19:58 -08:00

85 lines
2.6 KiB
TypeScript

import { useEffect } from "react"
import { useUIStateStore } from "../stores/uiStateStore.js"
import type { PendingAsk } from "../types.js"
export interface UseFocusManagementOptions {
showApprovalPrompt: boolean
pendingAsk: PendingAsk | null
}
export interface UseFocusManagementReturn {
/** Whether focus can be toggled between scroll and input areas */
canToggleFocus: boolean
/** Whether scroll area should capture keyboard input */
isScrollAreaActive: boolean
/** Whether input area is active (for visual focus indicator) */
isInputAreaActive: boolean
/** Manual focus override */
manualFocus: "scroll" | "input" | null
/** Set manual focus override */
setManualFocus: (focus: "scroll" | "input" | null) => void
/** Toggle focus between scroll and input */
toggleFocus: () => void
}
/**
* Hook to manage focus state between scroll area and input area.
*
* Focus can be toggled when text input is available (not showing approval prompt).
* The hook automatically resets manual focus when the view changes.
*/
export function useFocusManagement({
showApprovalPrompt,
pendingAsk,
}: UseFocusManagementOptions): UseFocusManagementReturn {
const { showCustomInput, manualFocus, setManualFocus } = useUIStateStore()
// Determine if we're in a mode where focus can be toggled (text input is available)
const canToggleFocus =
!showApprovalPrompt &&
(!pendingAsk || // Initial input or task complete or loading
pendingAsk.type === "followup" || // Followup question with suggestions or custom input
showCustomInput) // Custom input mode
// Determine if scroll area should capture keyboard input
const isScrollAreaActive: boolean =
manualFocus === "scroll" ? true : manualFocus === "input" ? false : Boolean(showApprovalPrompt)
// Determine if input area is active (for visual focus indicator)
const isInputAreaActive: boolean =
manualFocus === "input" ? true : manualFocus === "scroll" ? false : !showApprovalPrompt
// Reset manual focus when view changes (e.g., agent starts responding)
useEffect(() => {
if (!canToggleFocus) {
setManualFocus(null)
}
}, [canToggleFocus, setManualFocus])
/**
* Toggle focus between scroll and input areas
*/
const toggleFocus = () => {
if (!canToggleFocus) {
return
}
const prev = manualFocus
if (prev === "scroll") {
setManualFocus("input")
} else if (prev === "input") {
setManualFocus("scroll")
} else {
setManualFocus(isScrollAreaActive ? "input" : "scroll")
}
}
return {
canToggleFocus,
isScrollAreaActive,
isInputAreaActive,
manualFocus,
setManualFocus,
toggleFocus,
}
}