import { useEffect, useCallback } from 'react'; /** * Hook for enhanced keyboard navigation on Chromebooks */ export function useChromebookKeyboard() { const handleKeyDown = useCallback((e: KeyboardEvent) => { // Enhanced keyboard shortcuts for Chromebooks const { key, ctrlKey, metaKey, altKey, shiftKey } = e; // Chromebook-specific shortcuts if (metaKey || ctrlKey) { switch (key) { case 'k': // Focus search or command palette e.preventDefault(); const searchInput = document.querySelector('input[type="search"], input[placeholder*="search" i]') as HTMLInputElement; if (searchInput) { searchInput.focus(); searchInput.select(); } break; case 'Enter': // Submit forms with Ctrl/Cmd + Enter e.preventDefault(); const form = document.querySelector('form') as HTMLFormElement; if (form) { const submitButton = form.querySelector('button[type="submit"]') as HTMLButtonElement; if (submitButton && !submitButton.disabled) { submitButton.click(); } } break; case 'ArrowUp': case 'ArrowDown': // Navigate through messages or list items e.preventDefault(); const focusableElements = document.querySelectorAll( 'button, input, textarea, [tabindex]:not([tabindex="-1"]), [role="button"], [role="tab"]' ) as NodeListOf; const currentIndex = Array.from(focusableElements).indexOf(document.activeElement as HTMLElement); let nextIndex; if (key === 'ArrowUp') { nextIndex = currentIndex > 0 ? currentIndex - 1 : focusableElements.length - 1; } else { nextIndex = currentIndex < focusableElements.length - 1 ? currentIndex + 1 : 0; } focusableElements[nextIndex]?.focus(); break; } } // Escape key handling if (key === 'Escape') { // Close modals, clear inputs, or go back const activeElement = document.activeElement as HTMLElement; if (activeElement?.tagName === 'INPUT' || activeElement?.tagName === 'TEXTAREA') { // Clear input on Escape (activeElement as HTMLInputElement).value = ''; activeElement.blur(); } else { // Look for close buttons or back buttons const closeButton = document.querySelector('[aria-label*="close" i], [aria-label*="back" i]') as HTMLElement; if (closeButton) { closeButton.click(); } } } // Tab navigation enhancement if (key === 'Tab') { // Ensure proper tab order for Chromebooks const focusableElements = document.querySelectorAll( 'button:not([disabled]), input:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]), [role="button"]:not([disabled]), [role="tab"]' ); // Add visual focus indicators const addFocusIndicator = (element: Element) => { element.classList.add('keyboard-focus'); }; const removeFocusIndicator = (element: Element) => { element.classList.remove('keyboard-focus'); }; // Handle focus events focusableElements.forEach(element => { element.addEventListener('focus', () => addFocusIndicator(element)); element.addEventListener('blur', () => removeFocusIndicator(element)); }); } }, []); useEffect(() => { // Add global keyboard event listener document.addEventListener('keydown', handleKeyDown); // Cleanup return () => { document.removeEventListener('keydown', handleKeyDown); }; }, [handleKeyDown]); return { handleKeyDown }; } /** * Hook for managing focus in chat interfaces */ export function useChatFocus() { const focusMessageInput = useCallback(() => { const messageInput = document.querySelector('input[aria-label*="message" i], textarea[aria-label*="message" i]') as HTMLInputElement; if (messageInput) { messageInput.focus(); messageInput.select(); } }, []); const focusNextMessage = useCallback(() => { const messages = document.querySelectorAll('[role="article"]'); const currentMessage = document.activeElement?.closest('[role="article"]'); if (currentMessage) { const currentIndex = Array.from(messages).indexOf(currentMessage); const nextMessage = messages[currentIndex + 1] as HTMLElement; if (nextMessage) { nextMessage.focus(); } } else if (messages.length > 0) { (messages[0] as HTMLElement).focus(); } }, []); const focusPreviousMessage = useCallback(() => { const messages = document.querySelectorAll('[role="article"]'); const currentMessage = document.activeElement?.closest('[role="article"]'); if (currentMessage) { const currentIndex = Array.from(messages).indexOf(currentMessage); const previousMessage = messages[currentIndex - 1] as HTMLElement; if (previousMessage) { previousMessage.focus(); } } }, []); return { focusMessageInput, focusNextMessage, focusPreviousMessage }; }