diff --git a/apps/web/src/components/special-keys-panel.tsx b/apps/web/src/components/special-keys-panel.tsx index a7c368a..ed604a0 100644 --- a/apps/web/src/components/special-keys-panel.tsx +++ b/apps/web/src/components/special-keys-panel.tsx @@ -39,7 +39,7 @@ export const SpecialKeysPanel: React.FC = ({ onClose, onKeepFocus, }) => { - const { sendKey } = useSpecialKeys({ onSend }); + const { sendKey, clearModifier } = useSpecialKeys({ onSend }); if (!isOpen) return null; @@ -47,14 +47,29 @@ export const SpecialKeysPanel: React.FC = ({ e.preventDefault(); sendKey(key); onClose(); - onKeepFocus?.(); + // Always refocus terminal after sending + requestAnimationFrame(() => { + onKeepFocus?.(); + }); + }; + + const handleOverlayPointerDown = (e: React.PointerEvent) => { + e.preventDefault(); + clearModifier(); + onClose(); + requestAnimationFrame(() => { + onKeepFocus?.(); + }); }; return ( -
+
e.stopPropagation()} + onPointerDown={(e) => e.stopPropagation()} >
{EXPANDED_KEYS.map(({ key, label }) => ( @@ -62,7 +77,6 @@ export const SpecialKeysPanel: React.FC = ({ key={key} className="special-key-button" onPointerDown={(e) => handlePointerDown(e, key)} - onFocus={(e) => e.target.blur()} type="button" tabIndex={-1} > @@ -77,7 +91,6 @@ export const SpecialKeysPanel: React.FC = ({ key={key} className="special-key-button" onPointerDown={(e) => handlePointerDown(e, key)} - onFocus={(e) => e.target.blur()} type="button" tabIndex={-1} > diff --git a/apps/web/src/components/special-keys-strip.tsx b/apps/web/src/components/special-keys-strip.tsx index 70e77df..6fed01c 100644 --- a/apps/web/src/components/special-keys-strip.tsx +++ b/apps/web/src/components/special-keys-strip.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useSpecialKeys, type SpecialKey } from "../hooks/use-special-keys"; +import { useSpecialKeys, type SpecialKey, type ModifierKey } from "../hooks/use-special-keys"; interface SpecialKeysStripProps { onSend: (data: string) => void; @@ -8,11 +8,11 @@ interface SpecialKeysStripProps { onKeepFocus?: () => void; } -const PRIMARY_KEYS: { key: SpecialKey; label: string }[] = [ +const PRIMARY_KEYS: { key: SpecialKey; label: string; isModifier?: boolean }[] = [ { key: "escape", label: "Esc" }, { key: "tab", label: "Tab" }, - { key: "ctrl", label: "Ctrl" }, - { key: "alt", label: "Alt" }, + { key: "ctrl", label: "Ctrl", isModifier: true }, + { key: "alt", label: "Alt", isModifier: true }, { key: "up", label: "↑" }, { key: "down", label: "↓" }, { key: "left", label: "←" }, @@ -25,31 +25,38 @@ export const SpecialKeysStrip: React.FC = ({ onMoreClick, onKeepFocus, }) => { - const { sendKey } = useSpecialKeys({ onSend }); + const { sendKey, activeModifier } = useSpecialKeys({ onSend }); const handlePointerDown = (e: React.PointerEvent, key: SpecialKey) => { e.preventDefault(); sendKey(key); - onKeepFocus?.(); + // Always refocus terminal after sending + requestAnimationFrame(() => { + onKeepFocus?.(); + }); }; const handleMorePointerDown = (e: React.PointerEvent) => { e.preventDefault(); onMoreClick?.(); - onKeepFocus?.(); + requestAnimationFrame(() => { + onKeepFocus?.(); + }); }; return (
- {PRIMARY_KEYS.map(({ key, label }) => ( + {PRIMARY_KEYS.map(({ key, label, isModifier }) => ( @@ -58,7 +65,6 @@ export const SpecialKeysStrip: React.FC = ({