Skip to content

Commit

Permalink
feat: useFocusTrap
Browse files Browse the repository at this point in the history
  • Loading branch information
mrcaidev committed Aug 4, 2022
1 parent 866b54d commit 3c1f94b
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 0 deletions.
3 changes: 3 additions & 0 deletions etc/hooks.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export interface UseCounterResult {
set: (value: number) => void;
}

// @public
export function useFocusTrap(firstRef: RefObject<HTMLElement>, lastRef: RefObject<HTMLElement>): void;

// @public
export function useHover(ref: RefObject<HTMLElement | null>, options?: UseHoverOptions): boolean;

Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { useClickOutside } from "./use-click-outside";
export { useConst } from "./use-const";
export { useConstFn } from "./use-const-fn";
export { useCounter, type UseCounterResult } from "./use-counter";
export { useFocusTrap } from "./use-focus-trap";
export { useHover, type UseHoverOptions } from "./use-hover";
export { useKeydown, type ModifierKeys } from "./use-keydown";
export {
Expand Down
29 changes: 29 additions & 0 deletions src/use-focus-trap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useEffect, type RefObject } from "react";

/**
* Trap the tab focus between two elements.
* @param firstRef - A ref object of the element at the start of the trap.
* @param lastRef - A ref object of the element at the end of the trap.
*/
export function useFocusTrap(
firstRef: RefObject<HTMLElement>,
lastRef: RefObject<HTMLElement>
) {
const handleTab = (e: KeyboardEvent) => {
if (e.code !== "Tab") return;
if (e.shiftKey && document.activeElement === firstRef.current) {
e.preventDefault();
lastRef.current?.focus();
} else if (!e.shiftKey && document.activeElement === lastRef.current) {
e.preventDefault();
firstRef.current?.focus();
}
};

useEffect(() => {
document.addEventListener("keydown", handleTab);
return () => document.removeEventListener("keydown", handleTab);

// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}

0 comments on commit 3c1f94b

Please sign in to comment.