Refactor UI imports and update component paths
Some checks failed
Build Frontend / build (push) Failing after 7s
Some checks failed
Build Frontend / build (push) Failing after 7s
Replaces imports from 'components/ui' with 'components/common' across the app and dashboard pages, and updates model and API imports to use new paths under 'lib'. Removes redundant authentication checks from several dashboard pages. Adds new dashboard components and utility files, and reorganizes hooks and services into the 'lib' directory for improved structure.
This commit is contained in:
160
lib/hooks/use-chromebook-keyboard.tsx
Normal file
160
lib/hooks/use-chromebook-keyboard.tsx
Normal file
@@ -0,0 +1,160 @@
|
||||
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<HTMLElement>;
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user