Merge terminal tab focus retention

* commit '050cfc89e':
  fix(desktop): retain terminal focus after tab actions

Signed-off-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz>
This commit is contained in:
npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta
2026-08-02 21:57:25 -04:00
2 changed files with 34 additions and 3 deletions
@@ -159,6 +159,30 @@ test("mounted IME paths neither toggle nor emit preedit text", async () => {
assert.deepEqual(calls.input, ["か"]);
});
test("tab actions restore terminal input focus", async () => {
const { view } = fixture();
await ready(view);
toggleChord();
const input = view.getByLabelText("Terminal input");
await waitFor(() => assert.equal(document.activeElement, input));
const actions = [
["select", view.getByRole("tab")],
["close", view.getByLabelText("Close SHELL")],
["new", view.getByLabelText("New Buzz Term tab")],
];
for (const [label, target] of actions) {
target.focus();
assert.equal(document.activeElement, target, `${label} takes focus`);
fireEvent.click(target);
assert.equal(
document.activeElement,
input,
`${label} restores terminal focus`,
);
}
});
const EMPTY_FRAME = {
cursor: { column: 0, line: 0, visible: false },
full: false,
@@ -391,6 +391,13 @@ export function TerminalSubstrate({
gridRef.current?.paint(context, TERMINAL_CELL_METRICS, terminalPalette);
}, [activeSessionId, cursorPainted, frames, terminalPalette]);
const runTabAction = (action: () => void) => {
action();
if (owner === "terminal") {
textareaRef.current?.focus({ preventScroll: true });
}
};
return (
<section
aria-label="Buzz Term"
@@ -431,7 +438,7 @@ export function TerminalSubstrate({
aria-selected={session.active}
className="buzz-terminal-tab-select"
disabled={session.closing}
onClick={() => onSelectSession(session.id)}
onClick={() => runTabAction(() => onSelectSession(session.id))}
role="tab"
type="button"
>
@@ -444,7 +451,7 @@ export function TerminalSubstrate({
aria-label={`Close ${session.title}`}
className="buzz-terminal-close"
disabled={session.closing}
onClick={() => onCloseSession(session.id)}
onClick={() => runTabAction(() => onCloseSession(session.id))}
type="button"
>
×
@@ -454,7 +461,7 @@ export function TerminalSubstrate({
<button
aria-label="New Buzz Term tab"
className="buzz-terminal-new-tab"
onClick={onNewSession}
onClick={() => runTabAction(onNewSession)}
type="button"
>
+