import { Box, Text } from 'ink'; import type { PaneId } from './audit-state'; interface Props { focused: PaneId; modal: 'remediate' | 'reaudit-prompt' | 'celebration' | 'analyzing' | null; /** Transient confirmation that takes over the left side when set. */ flashMessage?: string | null; /** * Whether the currently-selected finding has a runnable * remediation. Drives whether "Remediate: r" appears in the * findings/detail bindings — surfacing it on a non-actionable * finding (e.g. capability_abi) misleads the user into thinking * `r` will fix it. */ findingActionable?: boolean; } function findingsBar(actionable: boolean): string { return actionable ? 'Focus: · Remediate: r · Back: ' : 'Focus: · Back: '; } function detailBar(actionable: boolean): string { return actionable ? 'Remediate: r · Copy: y · Back: ' : 'Copy: y · Back: '; } export function KeyBar({ focused, modal, flashMessage, findingActionable = false }: Props) { let left: string; if (flashMessage) { left = flashMessage; } else if (modal === 'remediate') { left = 'Run: · Cancel: '; } else if (modal === 'reaudit-prompt') { left = 'Yes: Y/ · No: n/'; } else if (modal === 'celebration') { left = 'Re-audit: R · Quit: q · Dismiss: '; } else if (modal === 'analyzing') { left = 'Analyzing system… (q to quit)'; } else if (focused === 'findings') { left = findingsBar(findingActionable); } else if (focused === 'detail') { left = detailBar(findingActionable); } else if (focused === 'categories') { left = 'Focus: '; } else if (focused === 'log') { left = 'Scroll: ↑↓ · Copy: y · Back: '; } else { left = ''; } // width="100%" + justifyContent="space-between" pins the two // groups to opposite edges; without an explicit width the flexbox // shrinks to content and the items end up adjacent. // Right side hosts globals: re-audit + help + quit. They're // always available regardless of focused pane / modal state, so // the user can discover them anywhere. return ( {left} R re-audit · t theme · ? help · q quit ); }