From 96f6512ab0633f56c45d7ef6c2132f8e16ab7a99 Mon Sep 17 00:00:00 2001 From: Mallik Cheripally Date: Thu, 8 Aug 2024 21:00:37 +0530 Subject: [PATCH] feat: enhance keyboard navigation in useFocusCycling hook Improve the Tab key handling to correctly cycle focusable elements both forward and backward. This update ensures better accessibility by addressing edge cases and refining the focus cycle logic. --- src/hooks/useFocusCycling.ts | 37 ++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/hooks/useFocusCycling.ts b/src/hooks/useFocusCycling.ts index cb2a480..994ade1 100644 --- a/src/hooks/useFocusCycling.ts +++ b/src/hooks/useFocusCycling.ts @@ -8,10 +8,7 @@ import { useEffect } from 'react'; * @param {React.RefObject} containerRef - The ref of the container element. * @param {string[]} [customSelectors=[]] - Additional selectors for custom focusable elements. */ -const useFocusCycling = ( - containerRef: React.RefObject, - customSelectors: string[] = [] -) => { +const useFocusCycling = (containerRef: React.RefObject, customSelectors: string[] = []) => { useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (!containerRef.current) return; @@ -23,23 +20,35 @@ const useFocusCycling = ( 'textarea', 'select', 'details', - '[tabindex]:not([tabindex="-1"])' + '[tabindex]:not([tabindex="-1"])', ]; const selectors = defaultSelectors.concat(customSelectors).join(','); - const focusableElements = Array.from( - containerRef.current.querySelectorAll(selectors) - ).filter((el) => !el.hasAttribute('disabled')); + const focusableElements = Array.from(containerRef.current.querySelectorAll(selectors)).filter( + (el) => !el.hasAttribute('disabled'), + ); const currentIndex = focusableElements.indexOf(document.activeElement as HTMLElement); if (event.key === 'Tab') { - if (event.shiftKey && currentIndex === 0) { - focusableElements[focusableElements.length - 1].focus(); - event.preventDefault(); - } else if (!event.shiftKey && currentIndex === focusableElements.length - 1) { - focusableElements[0].focus(); - event.preventDefault(); + if (event.shiftKey) { + // Cycle backward + if (currentIndex === 0) { + focusableElements[focusableElements.length - 1].focus(); + event.preventDefault(); + } else { + focusableElements[currentIndex - 1].focus(); + event.preventDefault(); + } + } else { + // Cycle forward + if (currentIndex === focusableElements.length - 1) { + focusableElements[0].focus(); + event.preventDefault(); + } else { + focusableElements[currentIndex + 1].focus(); + event.preventDefault(); + } } } };