mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-04 09:13:08 +00:00
refactor: synchronize focused menu index with refs for improved keyboard navigation
- Introduced a ref to keep the focused menu index in sync with state, enhancing keyboard navigation within the terminal context menu. - Updated event handlers to utilize the ref for managing focus, ensuring consistent behavior during menu interactions. - Simplified dependencies in the effect hook for better performance and clarity.
This commit is contained in:
@@ -75,6 +75,7 @@ export function TerminalPanel({
|
|||||||
const isMacRef = useRef(false);
|
const isMacRef = useRef(false);
|
||||||
const contextMenuRef = useRef<HTMLDivElement>(null);
|
const contextMenuRef = useRef<HTMLDivElement>(null);
|
||||||
const [focusedMenuIndex, setFocusedMenuIndex] = useState(0);
|
const [focusedMenuIndex, setFocusedMenuIndex] = useState(0);
|
||||||
|
const focusedMenuIndexRef = useRef(0);
|
||||||
|
|
||||||
// Detect platform on mount
|
// Detect platform on mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -683,12 +684,18 @@ export function TerminalPanel({
|
|||||||
// Context menu actions for keyboard navigation
|
// Context menu actions for keyboard navigation
|
||||||
const menuActions = ["copy", "paste", "selectAll", "clear"] as const;
|
const menuActions = ["copy", "paste", "selectAll", "clear"] as const;
|
||||||
|
|
||||||
|
// Keep ref in sync with state for use in event handlers
|
||||||
|
useEffect(() => {
|
||||||
|
focusedMenuIndexRef.current = focusedMenuIndex;
|
||||||
|
}, [focusedMenuIndex]);
|
||||||
|
|
||||||
// Close context menu on click outside or scroll, handle keyboard navigation
|
// Close context menu on click outside or scroll, handle keyboard navigation
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!contextMenu) return;
|
if (!contextMenu) return;
|
||||||
|
|
||||||
// Reset focus index and focus menu when opened
|
// Reset focus index and focus menu when opened
|
||||||
setFocusedMenuIndex(0);
|
setFocusedMenuIndex(0);
|
||||||
|
focusedMenuIndexRef.current = 0;
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
const firstButton = contextMenuRef.current?.querySelector<HTMLButtonElement>('[role="menuitem"]');
|
const firstButton = contextMenuRef.current?.querySelector<HTMLButtonElement>('[role="menuitem"]');
|
||||||
firstButton?.focus();
|
firstButton?.focus();
|
||||||
@@ -697,6 +704,11 @@ export function TerminalPanel({
|
|||||||
const handleClick = () => closeContextMenu();
|
const handleClick = () => closeContextMenu();
|
||||||
const handleScroll = () => closeContextMenu();
|
const handleScroll = () => closeContextMenu();
|
||||||
const handleKeyDown = (e: KeyboardEvent) => {
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
const updateFocusIndex = (newIndex: number) => {
|
||||||
|
focusedMenuIndexRef.current = newIndex;
|
||||||
|
setFocusedMenuIndex(newIndex);
|
||||||
|
};
|
||||||
|
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case "Escape":
|
case "Escape":
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -704,16 +716,16 @@ export function TerminalPanel({
|
|||||||
break;
|
break;
|
||||||
case "ArrowDown":
|
case "ArrowDown":
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setFocusedMenuIndex((prev) => (prev + 1) % menuActions.length);
|
updateFocusIndex((focusedMenuIndexRef.current + 1) % menuActions.length);
|
||||||
break;
|
break;
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setFocusedMenuIndex((prev) => (prev - 1 + menuActions.length) % menuActions.length);
|
updateFocusIndex((focusedMenuIndexRef.current - 1 + menuActions.length) % menuActions.length);
|
||||||
break;
|
break;
|
||||||
case "Enter":
|
case "Enter":
|
||||||
case " ":
|
case " ":
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
handleContextMenuAction(menuActions[focusedMenuIndex]);
|
handleContextMenuAction(menuActions[focusedMenuIndexRef.current]);
|
||||||
break;
|
break;
|
||||||
case "Tab":
|
case "Tab":
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -731,7 +743,7 @@ export function TerminalPanel({
|
|||||||
document.removeEventListener("scroll", handleScroll, true);
|
document.removeEventListener("scroll", handleScroll, true);
|
||||||
document.removeEventListener("keydown", handleKeyDown);
|
document.removeEventListener("keydown", handleKeyDown);
|
||||||
};
|
};
|
||||||
}, [contextMenu, closeContextMenu, focusedMenuIndex, handleContextMenuAction]);
|
}, [contextMenu, closeContextMenu, handleContextMenuAction]);
|
||||||
|
|
||||||
// Focus the correct menu item when navigation changes
|
// Focus the correct menu item when navigation changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user