fix(ui): allow Cmd/Ctrl+P when terminal is focused (#211)

* fix(ui): allow Cmd/Ctrl+P when terminal is focused

xterm.js uses a hidden <textarea class="xterm-helper-textarea"> for
keyboard capture.  isEditableTarget() was treating it as a real editable
field, which suppressed all global shortcuts (Cmd+P, Cmd+N, etc.) when
the terminal had focus.

Exclude that element so app-level keybindings remain reachable.

* fix(ui): hide empty quick-open results area and reduce bottom padding

The results container was always rendered with pb-2, leaving visible
empty space below the search input when there were no results.
Conditionally render the results div only when there is content, and
reduce padding from pb-2 to pb-1.
This commit is contained in:
Jinjing
2026-03-29 19:02:19 -07:00
committed by GitHub
parent b70ab2c4f7
commit 2ea48cd96b
2 changed files with 45 additions and 34 deletions
+9
View File
@@ -16,6 +16,15 @@ function isEditableTarget(target: EventTarget | null): boolean {
if (!(target instanceof HTMLElement)) {
return false
}
// xterm.js focuses a hidden <textarea class="xterm-helper-textarea"> for
// keyboard input. That element IS an editable target, but we must NOT
// suppress global shortcuts when the terminal itself is focused — otherwise
// Cmd/Ctrl+P and other app-level keybindings become unreachable.
if (target.classList.contains('xterm-helper-textarea')) {
return false
}
if (target.isContentEditable) {
return true
}
+36 -34
View File
@@ -206,7 +206,7 @@ export default function QuickOpen(): React.JSX.Element | null {
onClick={() => setVisible(false)}
>
<div
className="w-[660px] max-w-[90vw] bg-background border border-border rounded-lg shadow-2xl overflow-hidden pb-2"
className="w-[660px] max-w-[90vw] bg-background border border-border rounded-lg shadow-2xl overflow-hidden"
onClick={(e) => e.stopPropagation()}
>
{/* Search input */}
@@ -224,40 +224,42 @@ export default function QuickOpen(): React.JSX.Element | null {
/>
</div>
{/* Results list */}
<div ref={listRef} className="max-h-[300px] overflow-y-auto scrollbar-sleek pb-2">
{loading && (
<div className="px-3 py-6 text-center text-xs text-muted-foreground">
Loading files...
</div>
)}
{filtered.length === 0 && query.trim() && (
<div className="px-3 py-6 text-center text-xs text-muted-foreground">
No matching files
</div>
)}
{filtered.map((item, idx) => {
const lastSlash = item.path.lastIndexOf('/')
const dir = lastSlash >= 0 ? item.path.slice(0, lastSlash) : ''
const filename = item.path.slice(lastSlash + 1)
{/* Results list — only rendered when there is content to avoid empty padding */}
{(loading || query.trim()) && (
<div ref={listRef} className="max-h-[300px] overflow-y-auto scrollbar-sleek pb-1">
{loading && (
<div className="px-3 py-6 text-center text-xs text-muted-foreground">
Loading files...
</div>
)}
{filtered.length === 0 && query.trim() && (
<div className="px-3 py-6 text-center text-xs text-muted-foreground">
No matching files
</div>
)}
{filtered.map((item, idx) => {
const lastSlash = item.path.lastIndexOf('/')
const dir = lastSlash >= 0 ? item.path.slice(0, lastSlash) : ''
const filename = item.path.slice(lastSlash + 1)
return (
<button
key={item.path}
type="button"
className={`w-full flex items-center gap-2 px-3 py-1.5 text-left text-xs hover:bg-accent/50 ${
idx === selectedIndex ? 'bg-accent' : ''
}`}
onClick={() => handleSelect(item.path)}
onMouseEnter={() => setSelectedIndex(idx)}
>
<File size={14} className="text-muted-foreground flex-shrink-0" />
<span className="truncate text-foreground">{filename}</span>
{dir && <span className="truncate text-muted-foreground ml-1">{dir}</span>}
</button>
)
})}
</div>
return (
<button
key={item.path}
type="button"
className={`w-full flex items-center gap-2 px-3 py-1.5 text-left text-xs hover:bg-accent/50 ${
idx === selectedIndex ? 'bg-accent' : ''
}`}
onClick={() => handleSelect(item.path)}
onMouseEnter={() => setSelectedIndex(idx)}
>
<File size={14} className="text-muted-foreground flex-shrink-0" />
<span className="truncate text-foreground">{filename}</span>
{dir && <span className="truncate text-muted-foreground ml-1">{dir}</span>}
</button>
)
})}
</div>
)}
</div>
</div>
)