mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-11-10 16:21:22 +00:00
Fix keyboard navigation in host pickers
This commit is contained in:
1 parent
ef44faa7df
commit
7b9c634475
2 files changed
+20
-2
No files matched your search
@@ -97,15 +97,18 @@ const IS_MAC = typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(naviga
|
||||
const HostItem = memo(({
|
||||
host,
|
||||
isSelected,
|
||||
selectedItemRef,
|
||||
onSelect,
|
||||
onMouseEnter,
|
||||
}: {
|
||||
host: Host;
|
||||
isSelected: boolean;
|
||||
selectedItemRef?: React.Ref<HTMLDivElement>;
|
||||
onSelect: (host: Host) => void;
|
||||
onMouseEnter: () => void;
|
||||
}) => (
|
||||
<div
|
||||
ref={selectedItemRef}
|
||||
className={`flex items-center justify-between px-4 py-2.5 cursor-pointer transition-colors ${isSelected ? "bg-primary/15" : "hover:bg-muted/50"
|
||||
}`}
|
||||
onClick={() => onSelect(host)}
|
||||
@@ -192,6 +195,7 @@ const QuickSwitcherInner: React.FC<QuickSwitcherProps> = ({
|
||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const selectedItemRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Reset state when opening
|
||||
useEffect(() => {
|
||||
@@ -322,6 +326,14 @@ const QuickSwitcherInner: React.FC<QuickSwitcherProps> = ({
|
||||
return itemIndexMap.get(`${type}:${id}`) ?? -1;
|
||||
}, [itemIndexMap]);
|
||||
|
||||
const selectedItem = flatItems[selectedIndex];
|
||||
const selectedItemKey = selectedItem ? `${selectedItem.type}:${selectedItem.id}` : '';
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen || !selectedItemKey) return;
|
||||
selectedItemRef.current?.scrollIntoView({ block: "nearest" });
|
||||
}, [isOpen, selectedIndex, selectedItemKey]);
|
||||
|
||||
if (!isOpen) return null;
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
@@ -449,6 +461,7 @@ const QuickSwitcherInner: React.FC<QuickSwitcherProps> = ({
|
||||
key={host.id}
|
||||
host={host}
|
||||
isSelected={getItemIndex("host", host.id) === selectedIndex}
|
||||
selectedItemRef={getItemIndex("host", host.id) === selectedIndex ? selectedItemRef : undefined}
|
||||
onSelect={onSelect}
|
||||
onMouseEnter={() => setSelectedIndex(getItemIndex("host", host.id))}
|
||||
/>
|
||||
@@ -479,6 +492,7 @@ const QuickSwitcherInner: React.FC<QuickSwitcherProps> = ({
|
||||
return (
|
||||
<div
|
||||
key={tabId}
|
||||
ref={isSelected ? selectedItemRef : undefined}
|
||||
className={`flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${isSelected ? "bg-primary/15" : "hover:bg-muted/50"
|
||||
}`}
|
||||
onClick={() => {
|
||||
@@ -503,6 +517,7 @@ const QuickSwitcherInner: React.FC<QuickSwitcherProps> = ({
|
||||
return (
|
||||
<div
|
||||
key={workspace.id}
|
||||
ref={isSelected ? selectedItemRef : undefined}
|
||||
className={`flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${isSelected ? "bg-primary/15" : "hover:bg-muted/50"
|
||||
}`}
|
||||
onClick={() => {
|
||||
@@ -529,6 +544,7 @@ const QuickSwitcherInner: React.FC<QuickSwitcherProps> = ({
|
||||
return (
|
||||
<div
|
||||
key={session.id}
|
||||
ref={isSelected ? selectedItemRef : undefined}
|
||||
className={`flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${isSelected ? "bg-primary/15" : "hover:bg-muted/50"
|
||||
}`}
|
||||
onClick={() => {
|
||||
@@ -563,6 +579,7 @@ const QuickSwitcherInner: React.FC<QuickSwitcherProps> = ({
|
||||
return (
|
||||
<div
|
||||
key={shell.id}
|
||||
ref={isSelected ? selectedItemRef : undefined}
|
||||
className={`flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${
|
||||
isSelected ? "bg-primary/15" : "hover:bg-muted/50"
|
||||
}`}
|
||||
@@ -597,6 +614,7 @@ const QuickSwitcherInner: React.FC<QuickSwitcherProps> = ({
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
ref={getItemIndex("action", "local-terminal") === selectedIndex ? selectedItemRef : undefined}
|
||||
className={`flex items-center gap-3 px-4 py-2.5 cursor-pointer transition-colors ${
|
||||
getItemIndex("action", "local-terminal") === selectedIndex
|
||||
? "bg-primary/15"
|
||||
|
||||
@@ -128,7 +128,7 @@ export const AddToWorkspaceDialog: React.FC<AddToWorkspaceDialogProps> = ({
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
setSelectedIndex((i) => Math.max(i - 1, 0));
|
||||
} else if (e.key === ' ' || (e.key === 'Enter' && !(e.metaKey || e.ctrlKey))) {
|
||||
} else if (e.key === 'Enter' && !(e.metaKey || e.ctrlKey)) {
|
||||
if (items.length === 0) return;
|
||||
e.preventDefault();
|
||||
toggle(items[selectedIndex].id);
|
||||
@@ -180,7 +180,7 @@ export const AddToWorkspaceDialog: React.FC<AddToWorkspaceDialogProps> = ({
|
||||
{/* Jump-to hint */}
|
||||
<div className="px-4 py-2 flex items-center gap-2">
|
||||
<span className="text-xs text-muted-foreground">Pick one or more</span>
|
||||
<kbd className="text-[10px] text-muted-foreground bg-muted px-1 py-0.5 rounded">Space</kbd>
|
||||
<kbd className="text-[10px] text-muted-foreground bg-muted px-1 py-0.5 rounded">Enter</kbd>
|
||||
<span className="text-[10px] text-muted-foreground">toggle</span>
|
||||
<kbd className="text-[10px] text-muted-foreground bg-muted px-1 py-0.5 rounded">
|
||||
{typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform) ? '⌘' : 'Ctrl'}+Enter
|
||||
|
||||
Reference in new issue
Block a user