Skip to content

Commit

Permalink
fix: disable positive index guard by default; use hasPositiveIndices …
Browse files Browse the repository at this point in the history
…to control behavior, fixes #32
  • Loading branch information
theKashey committed Feb 13, 2022
1 parent 2e461f7 commit 6db9980
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 10 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ I've got a good [article about focus management, dialogs and WAI-ARIA](https://
- `whiteList=fn` you could _whitelist_ locations FocusLock should carry about. Everything outside it will ignore. For example - any modals.
- `as='div'` if you need to change internal `div` element, to any other. Use ref forwarding to give FocusLock the node to work with.
- `lockProps={}` to pass any extra props (except className) to the internal wrapper.
- `usePositiveIndices` to maintain a focus lock when elements exterior to the focus lock have a tabIndex greater than 0.
- `hasPositiveIndices=false` to support a focus lock behavior when any elements tabIndex greater than 0.

### Focusing in OSX (Safari/Firefox) is strange!
By default `tabbing` in OSX `sees` only controls, but not links or anything else `tabbable`. This is system settings, and Safari/Firefox obey.
Expand Down
13 changes: 10 additions & 3 deletions interfaces.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import {Ref} from "react";

export interface ReactFocusLockProps<ChildrenType = React.ReactNode, LockProps=Record<string, any>> {
export interface ReactFocusLockProps<ChildrenType = React.ReactNode, LockProps = Record<string, any>> {
disabled?: boolean;

/**
Expand All @@ -12,7 +12,7 @@ export interface ReactFocusLockProps<ChildrenType = React.ReactNode, LockProps=R
* can also accept a function with the first argument equals to element focus will be returned to
* in order to provide full control to the user space
*/
returnFocus?: boolean | FocusOptions | ((returnTo: Element)=> boolean | FocusOptions);
returnFocus?: boolean | FocusOptions | ((returnTo: Element) => boolean | FocusOptions);

/**
* used to control behavior or "returning focus back to the lock"
Expand Down Expand Up @@ -61,6 +61,13 @@ export interface ReactFocusLockProps<ChildrenType = React.ReactNode, LockProps=R
*/
noFocusGuards?: boolean | "tail";

/**
* Controls support a focus lock behavior when any elements tabIndex greater than 0.
* @default false
* @see - https://github.com/theKashey/react-focus-lock/issues/32
*/
hasPositiveIndices?: boolean;

/**
* named focus group for focus scattering aka combined lock targets
*/
Expand All @@ -83,7 +90,7 @@ export interface ReactFocusLockProps<ChildrenType = React.ReactNode, LockProps=R
/**
* Component to use, defaults to 'div'
*/
as?: string | React.ElementType<LockProps & {children: ChildrenType}>,
as?: string | React.ElementType<LockProps & { children: ChildrenType }>,
lockProps?: LockProps,

ref?: Ref<HTMLElement>;
Expand Down
15 changes: 9 additions & 6 deletions src/Lock.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const FocusLock = React.forwardRef(function FocusLockUI(props, parentRef) {
group,
className,
whiteList,
usePositiveIndices,
hasPositiveIndices,
shards = emptyArray,
as: Container = 'div',
lockProps: containerProps = {},
Expand All @@ -41,8 +41,6 @@ const FocusLock = React.forwardRef(function FocusLockUI(props, parentRef) {
onDeactivation: onDeactivationCallback,
} = props;

const maxTabIndex = usePositiveIndices ? 1 : 0;

const [id] = React.useState({});

// SIDE EFFECT CALLBACKS
Expand All @@ -65,7 +63,7 @@ const FocusLock = React.forwardRef(function FocusLockUI(props, parentRef) {
}, [onDeactivationCallback]);

useEffect(() => {
if(!disabled) {
if (!disabled) {
// cleanup return focus on trap deactivation
// sideEffect/returnFocus should happen by this time
originalFocusedElement.current = null;
Expand Down Expand Up @@ -139,8 +137,13 @@ const FocusLock = React.forwardRef(function FocusLockUI(props, parentRef) {
return (
<React.Fragment>
{hasLeadingGuards && [
<div key="guard-first" data-focus-guard tabIndex={disabled ? -1 : 0} style={hiddenGuard}/>, // nearest focus guard
<div key="guard-nearest" data-focus-guard tabIndex={disabled ? -1 : maxTabIndex} style={hiddenGuard}/>, // first tabbed element guard
// nearest focus guard
<div key="guard-first" data-focus-guard tabIndex={disabled ? -1 : 0} style={hiddenGuard}/>,

// first tabbed element guard
hasPositiveIndices
? <div key="guard-nearest" data-focus-guard tabIndex={disabled ? -1 : 1} style={hiddenGuard}/>
: null,
]}
{!disabled && (
<SideCar
Expand Down

0 comments on commit 6db9980

Please sign in to comment.