Giter Site home page Giter Site logo

thekashey / react-focus-on Goto Github PK

View Code? Open in Web Editor NEW
321.0 4.0 14.0 995 KB

🎯 Solution for WAI ARIA compatible modal dialogs or full-screen tasks, you were looking for

License: MIT License

TypeScript 98.68% HTML 1.32%
focus scroll aria lock

react-focus-on's Introduction

πŸ‘ React-Focus-On


lock and loaded!
Build status npm downloads bundle size

The final solution for WAI ARIA compatible Modal Dialogs or any full-screen tasks:

Now you could focus on a single task.

This is basically the inert

Minimal size - no more than 2kb, maximal - no more that 6kb. See sidecar example for details.

Example

Code sandbox example - https://codesandbox.io/s/p3vjp8mzw7

import {FocusOn} from 'react-focus-on';

<FocusOn
 onClickOutside={callback}
 onEscapeKey={callback}
 shards={[externalRef]}
>
 content you should be "focused" on
</FocusOn>

API

FocusOn

FocusOn - the focus on component

  • enabled - controls behaviour
  • [shards] - a list of Refs to be considered as a part of the Lock. A way to properly handle portals or scattered lock.


  • [gapMode] - the way removed ScrollBar would be compensated - margin(default), or padding. See scroll-locky documentation to find the one you need.
  • [noIsolation] - disables aria-hidden isolation
  • [inert] - enables pointer-events isolation (☠️ dangerous, use to disable "parent scrollbars", refer to react-remove-scroll documentation)
  • [allowPinchZoom] - enables "pinch-n-zoom" behavior. By default it might be prevented, refer to react-remove-scroll documentation
  • [preventScrollOnFocus] - prevents a side effect of a programatic page scroll caused by focusing elements. Especially useful to address modal animations.

  • [onActivation] - on activation callback
  • [onDeactivation] - on deactivation callback

  • [onClickOutside] - on click outside of "focus" area. (actually on any event "outside")
  • [onEscapeKey] - on Esc key down (and not defaultPrevented)

Additional API

Exposed from React-Focus-Lock

  • AutoFocusInside - to mark autofocusable element
  • MoveFocusInside - to move focus inside a component on mount
  • InFocusGuard - to "guard" a shard node (place an invisible node before and after)

See react-focus-lock documentation for details.

Exposed from React-Remove-Scroll

  • classNames.fullWidth - "100%" width (will not change on scrollbar removal)
  • classNames.zeroRight - "0" right (will not change on scrollbar removal)

See react-remove-scroll for details.

PS: Version 1 used React-scroll-locky which was replaced by remove-scroll.

Size

  • (🧩 full) 5.7kb after compression (excluding tslib).

  • (πŸ‘ UI) 2kb, visual elements only
  • (πŸš— sidecar) 4kb, side effects

Import full

import {FocusOn} from 'react-focus-on';

<FocusOn>
 {content}
</FocusOn> 

Import UI only

import {FocusOn} from 'react-focus-on/UI';
import {sidecar} from "use-sidecar";

const FocusOnSidecar = sidecar(  
  () => import(/* webpackPrefetch: true */ "react-focus-on/sidecar")
);

<FocusOn
    sideCar={FocusOnSidecar}
>
 {content}
</FocusOn> 

React versions

  • v1 and v2 might work with React 15/16
  • v3 require React 16.8+ (hooks)

Licence

MIT

react-focus-on's People

Contributors

alexandernanberg avatar benoitgrelard avatar cee-chen avatar dremora avatar endpoint-vtsang avatar magnusottosson avatar msftenhanceprovenance avatar omerdemirkan avatar thekashey avatar thompsongl avatar tkajtoch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

react-focus-on's Issues

Use with react-transition-group doesn't clear aria-hidden attributes

I have an implementation where I'm using react-focus-on with react-transition-group. The idea is that as I transition in some JSX I lock focus to the area I need. The initial load is fine but when the section is closed but clicking outside or escape key, the elements that were hidden still have the aria-hidden attributes as well the button having pointer-events: none.

https://codesandbox.io/s/dry-wind-4h4tt?file=/src/App.js

Is there a way to undo the aria-hidden attributes that were set? Or perhaps a suggestion on a different approach?

Mixed module semantics breaks rollup build

Although the source is authored with ES-Modules, there is a require statement inside Combination.tsx. Mixing both import statements and require statements is invalid according to the spec.

const SideCar = require('./sidecar').default;

It seems to me that this code should load the component lazily and makes use of a webpack specific behaviour which will load that code lazily. Nowadays it probably should use the standardized import() call instead.

FYI: There is a workaround for the invalid portion by setting the transformMixedEsModules: true for @rollup/plugin-commonjs, but that just turns it into a synchronous import.

Console error [Intervention]

[Intervention] Ignored attempt to cancel a touchmove event with cancelable=false
Possible fix: if (event.cancelable) event.preventDefault();

Allow `style` prop on <FocusOn />

Similar to how className is applied, style could be applied to the main div (the one with the data-focus-lock-disabled attribute).

Happy to open a pull request, but wanted to ask your preference:

  1. Allow style prop only.
  2. Allow lockProps prop similar to react-focus-lock where any valid HTML or React attribute can be applied.

After switching to react-focus-on from react-focus-lock this has been the only API gap. Thanks for your work!

Missing Prop `noFocusGuards`

Hi, I'm using this library and so far it's been working great but unfortunately I need noFocusGuards prop which is currently not exposed.

Happy to open a pull request, but I wanted to ask your preference:

Allow noFocusGuards prop only.

Interacting with a canvas element inside a focus lock

I'm rendering a canvas with interactive elements that take keyboard input inside a FocusOn container. With the focusLock enabled, I am unable to add any input to these elements. I believe it makes sense since they aren't actually focusable text inputs but I haven't found a way to work around this. I was hoping to find some way to make the focus lock "ignore" that area but haven't succeeded.

P.S. Thanks for the awesome library.

Bumping react-focus-lock to 2.9.4

Hi,

I am using a react-focus-lock in a nextjs app and I am running an issue with the no shadowroot error in
next.js frameworks.

react-focus-on have a dependency on react-focus-lock which relies on focus-lock.

There is a bug in focus-lock":"0.11.5 which causes unit tests to fail with no shadowroot error in
next.js frameworks. The issue is resolved in [email protected], but requires bumping [email protected] to resolve the issue in this package.

onClickOutside is never triggered with React portals

I'm currently experimenting with react-focus-on in a project of mine to see if that works as I need it. So far, it did what I expected, but I cannot get one thing to work: onClickOutside is never triggered for me, so I cannot automatically close popups. I'm testing on Firefox mostly, but I guess this doesn't play a role here.

My portal render code is this:

public render(): React.ReactNode {
    const { children, container = document.body } = this.props;
    const { open, options } = this.state;

    const className = this.getEffectiveClassNames([
        "portal",
    ]);

    const element = <div ref={this.contentRef}>
        {children}
    </div>;

    return (
        open && createPortal(
            <FocusOn
                shards={[this.contentRef]}
                className={className}
                enabled={true}
                scrollLock={true}
                focusLock={true}
                autoFocus={true}
                returnFocus={true}
                onClickOutside={this.handlClickOutside}
                onEscapeKey={this.handleEscapeKey}
            >
                {element}
            </FocusOn>, container,
        )
    );
}

First I rendered the children directly in the portal element, then I tried to wrap it with a div and use the ref of that for the shards property. But that didn't change anything. I'm assuming here that shards plays a role in this misfunction, but I could be completely wrong.

Can you please tell me how this should be implemented actually? The documentation is pretty sparse overall. Thanks.

Activation lifecycle bugs introduced in #19

Hi @theKashey

Since #19 got merged and 3.1.1 got released, the activation lifecycle is not working properly.
I haven't managed to specifically find out why, but he's a simple reproduction:

react-focus-on 3.1.0

Working activation lifecycle
https://codesandbox.io/s/react-focus-on-310-wg4js

react-focus-on 3.1.1

Activation lifecycle not working correctly
https://codesandbox.io/s/react-focus-on-311-3rz2r


Both examples are exactly the same, only the version of react-focus-on differs.
Pay attention to the logs:

  • in 3.1.0 when opening you get activated, and when closing you get deactivated
  • in 3.1.1 when opening you get deactivated and activated, and when closing you get nothing

This is a breaking issue for us and I believe we should rollback that PR (#19) until we can figure out a way to incorporate the intended fix (#17) without breaking the lifecycle.

Let me know what you think!

✌️

Adding support for `react-focus-lock` `crossFrame` prop

Hey again @theKashey! πŸ‘‹ We just got a question about iframe behavior from one of our consumers. While I was looking for a solution or workaround, I noticed that react-focus-lock supports a crossFrame prop that was added a few years ago (theKashey/react-focus-lock#104) and would likely be exactly what we need.

Is there any chance we could extend FocusOn to allow the same crossFrame configuration and pass that to FocusLock? πŸ™ That would be incredibly helpful to us. Would you accept a PR with this addition?

Heading, paragraph text are not selectable inside `FocusOn`

With the addition of react-focus-on, we got this strange behavior of not being able to select any text inside the FocusOn component.

  • I don't see conflicting CSS like user-select. pointer-events is set to auto but that shouldn't stop text-selection

I couldn't figure out what caused the issue. What could be the reason?

"Sidecar medium was not found" when running unit tests with jest

Hello! I recently added this library to add accessibility features to a modal dialog component (and it works like a charm, thanks!) but I'm having some issues with the tests that use that component. The tests are now failing with the error Sidecar medium was not found.

Using react-testing-library and jest. The test also gives some warnings about updates to sidecar not being wrapped inside an act function, which they are so that seems strange too

Warning: An update to Sidecar inside a test was not wrapped in act(...).
      
When testing, code that causes React state updates should be wrapped into act(...):
      
      act(() => {
        /* fire events that update state */
      });
      /* assert on the output */

Unfortunately the error messages aren't very helpful so I would appreciate some advice

Thanks

iOS: keyboard popping up on input focus scrolls locked body

Hi!

I use react-focus-on in my app for implementing proper modal dialogs. Discovered an issue on iOS: when dialog contains a long form and user clicks on input, Safari puts focus on it, pops up keyboard and shifts viewport up so that the input stays in the viewport above the keyboard. The problem is that locked document scroll is also affected by this behaviour. I’ve set up a reproduction sandbox and made a recording demonstrating the issue:

record.mp4

By the end of the recording you can see the bottom of the page. Is it possible to prevent document scroll in this case?

Click outside should be bound to mousedown / touchstart rather than click / touchend

Hi @theKashey,

After doing some research, I found another behaviour similar to the work we did on the escape key behaviour (#15).

Similarly here, looking at what the OS does for all types of modal layers (things like save system menus, app menus, right click menus, open selects, etc) click outside always executes instantly as soon as pressing down, on mousedown basically.

I believe we should also bind to mousedown rather than click?

Small change again, but I think offers much better consistency.
Let me know your thoughts, I'll send you a PR for it as well in a minute.

Cheers πŸ‘

Support passing `focusOptions` to `react-focus-lock`

As of 2.7.0, react-focus-lock has supported a focusOptions prop, primarily for allowing consumers to pass preventScroll to the initial focus event. react-focus-on unfortunately has not exposed nor is passing that prop directly to react-focus-lock, which potentially leads to scroll jumping issues that cannot be overridden (see theKashey/react-focus-lock#162 for more info).

It should be relatively trivial to pull focusOptions from props and pass it directly to <ReactFocusLock> here: https://github.com/theKashey/react-focus-on/blob/master/src/UI.tsx#L49

Add className prop

Hi there i'm trying to add some styling to the div that is rendered using styled-components - but no className prop seems to be passed down to the underlying div.

onEscapeKey handler doesn't work with IE11 or some versions of Edge

The following code doesn't work in IE:

var code = event.key || event.keyCode;
if ((event.code === 'Escape' || code === 'Escape' || code === 27) && _this.props.onEscapeKey) {
  _this.props.onEscapeKey(event);
}

it should be:

if ((event.code === 'Escape' || event.key === 'Escape' || event.keyCode === 27) && _this.props.onEscapeKey) {
  _this.props.onEscapeKey(event);
}

IE11 sets event.key to "Esc" so the keyCode is skipped and thereby ignored.

It seems to work correctly in Edge 18.

returnToFocus option

Hi,

First, thanks for this great library.
I was wondering why returnToFocus was hardcoded as true and not passed as an option to FocusLock like the others. (see https://github.com/theKashey/react-focus-on/blob/master/src/UI.tsx#L37)

The use case I am trying to provide is, by default let your library handle the return focus, but if the user passes a custom ref to focus when the modal gets close, focus on that instead.

The issue is that for this to work, I have to write my ref.focus() in something like setImmediate or requestAnimationFrame to wait for the normal returnToFocus to do its thing first (I'm doing this in onDeactivation callback). Instead I would like to set returnToFocus={false} when a custom ref is passed into my component.

I hope this make sense.
I tested it with react-focus-lock and it worked well by setting returnToFocus={false} and focusing my own thing using onDeactivation callback.

Thanks πŸ™

Change repository description

Currently, the repository description is The final solution for WAI ARIA compatible modal dialogs or full-screen tasks.. Without going into the details, the term "final solution" has a terrible connotation.

May I suggest changing this to something like "the ultimate solution"?

"React does not recognize the `gapMode` prop on a DOM element" warning

After updating to 3.8.0 I am getting the following warning:

    Warning: React does not recognize the `gapMode` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `gapmode` instead. If you accidentally passed it from a parent component, remove it from the DOM element.
        at div
        at /home/timo/Code/asti/my-app/node_modules/react-remove-scroll/dist/es5/UI.js:16:21
        at FocusLockUI (/home/timo/Code/asti/my-app/node_modules/react-focus-lock/dist/cjs/Lock.js:40:31)
        at /home/timo/Code/asti/my-app/node_modules/react-focus-on/dist/es5/UI.js:10:20
        at div
        at Modal (/home/timo/Code/asti/my-app/src/components/Modal/Modal.tsx:12:34)

React@17 event delegation issue

Hi! πŸ‘‹

Firstly, thanks for your work on this project! πŸ™‚

Today I used patch-package to patch [email protected] for the project I'm working on.

Here is the diff that solved my problem:

diff --git a/node_modules/react-focus-on/dist/es2015/Effect.js b/node_modules/react-focus-on/dist/es2015/Effect.js
index 06fe55c..1994a65 100644
--- a/node_modules/react-focus-on/dist/es2015/Effect.js
+++ b/node_modules/react-focus-on/dist/es2015/Effect.js
@@ -50,15 +50,15 @@ export function Effect(_a) {
             mouseTouches.current = event.touches.length;
         };
         if (activeNode) {
-            document.addEventListener('keydown', onKeyDown);
-            document.addEventListener('mousedown', onMouseDown);
-            document.addEventListener('touchstart', onTouchStart);
-            document.addEventListener('touchend', onTouchEnd);
+            document.addEventListener('keydown', onKeyDown, { capture: true });
+            document.addEventListener('mousedown', onMouseDown, { capture: true });
+            document.addEventListener('touchstart', onTouchStart, { capture: true });
+            document.addEventListener('touchend', onTouchEnd, { capture: true });
             return function () {
-                document.removeEventListener('keydown', onKeyDown);
-                document.removeEventListener('mousedown', onMouseDown);
-                document.removeEventListener('touchstart', onTouchStart);
-                document.removeEventListener('touchend', onTouchEnd);
+                document.removeEventListener('keydown', onKeyDown, { capture: true });
+                document.removeEventListener('mousedown', onMouseDown, { capture: true });
+                document.removeEventListener('touchstart', onTouchStart, { capture: true });
+                document.removeEventListener('touchend', onTouchEnd, { capture: true });
             };
         }
     }, [activeNode, onClickOutside, onEscapeKey]);

This issue body was partially generated by patch-package.

Upgrade react-focus-lock to 2.9.4

Hello πŸ‘‹ !

I'm running into unit test issues that fail with no shadowRoot. From what I can gather, it is similar to issues described in react-focus-lock:

I was able to get this working by resolving focus-lock to v0.11.6 in my package.json. Is it possible to upgrade react-focus-lock to the latest version (v2.9.4)? It looks like I'm unable to open up a PR with my local branch.

module logging to console

im seeing lots of logging in my console with the latest release like this:

initialization: 0.0050000089686363935

Shadow DOM

Would it be possible to have a new version of this library, with the latest versions of its dependencies? Looks like react-focus-lock recently got support, and it would be awesome to have it in react-focus-on as well!

Allow ability to disable specific functionality

In one of our components, we have a prop which allows you to be able to disable/enable scrolling while it's open. We'd like to keep this available for backwards compatibility.

What I propose is a prop like disableScrollLock to achieve this.

as={Component} not exposed from react-focus-lock

I am trying to use react-focus-on with the as= prop to render my own nav without it being nested inside a div. As seen here:
image
however, it doesnt seem to be exposed from react-focus-lock.

EDIT: Have done a little digging and it seems internally the as is being used as RemoveScroll, and RemoveScroll is using a div, maybe we could pass through the as prop to removeScroll and that renders the component if provided?

Ive tried to use and implement forwardProps and that removed the div but then the lock didnt work.

Can't resolve tslib

After running npm install on a project with dependencies on multiple major versions of tslib (i.e., ^1.0.0 and ^2.0.0), I'm getting the following error:

ERROR in: ./node_modules/react-focus-on/dist/es2015/Combination.js
Module not found: Error: Can't resolve 'tslib' in '<path>/node_modules/react-focus-on/dist/es2015' 

Should tslib be declared as a dependency?

Escape key should be bound on keydown rather than keyup

Hi @theKashey,

Looking at what the OS does for all types of modal layers (things like save dialog, confirmation dialogs, open menus, open selects, etc) close on escape always executes instantly as soon as touching the escape key, on keydown basically.

https://github.com/theKashey/react-focus-on/blob/master/src/Effect.tsx#L66

We are bound to keyup here which puts us a bit behind in terms of timing, and offers a different UX.

I believe we should also bind to keydown rather than keyup?

Small change, but I think offers much better consistency.
Let me know your thoughts, I can do a PR if needed, although I doubt you need one considering the change.

Cheers πŸ‘

Incompatibility with clipboard utilities in certain browsers?

So I have a modal with a copy-to-clipboard functionality, using sindresorhus/copy-text-to-clipboard. This consistently works as long as my modal isn’t wrapped in react-focus-on. With it, copying consistently stops working in Chrome and Firefox. In Safari it continues to work, somehow. I don’t experience this problem at all using the standalone react-focus-lock.

I’m not entirely sure what’s going on, but I think the way copying to clipboard works in some browsers, is that an event (maybe the one proving that a user did indeed interact and that the code should be allowed to manipulate the OS’ clipboard?) propagates all the way up to document?

I’m guessing this is some sort of side effect of stopping event propagation from scroll events in the scroll lock part of this utility, so if it’s possible to pinpoint these events more specifically and leave others alone, that’d probably be an improvement.

Warnings after upgrading to v3.0.0

Started getting the following warnings after upgrading:

Warning: Unknown event handler property `onActivation`. It will be ignored.
Warning: Unknown event handler property `onDeactivation`. It will be ignored.

Prevent focus removal for external resources

Hi,

How can I prevent pointer-events: none being applied to external resources(non React elements)?

Example:
I have a sticky chat button loaded via Google tag manager. It renders outside root. Is there a way to apply it to shards somehow? or even better, prevent adding pointer-events: none to anything outside #root when <FocusOn> is enabled?

Unable to activate links or submit forms within FocusOn

I have modals that contain links and forms (with some custom validation) that stopped working when I added FocusOn to them. Digging deeper, it appears this onClick listener that's passed to focus-lock is the culprit https://github.com/theKashey/react-focus-on/blob/master/src/component.tsx#L33. Unfortunately removing it causes any clicks within the modal to trigger a the onClickOutside callback.

Any tips for moving forward without having to add custom click handlers to everything?

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.

`gapMode` prop/API is not actually used

Despite being documented in the main README, setting gapMode="padding" as a prop does not appear to correctly change the CSS applied to the page body to set padding-right instead of margin-right (which the underlying react-remove-scroll-bar library implies it should).

gapMode usage appears to be nonexistent, and its original implementation no longer exists in the codebase.

Demo of broken behavior: https://codesandbox.io/s/romantic-jennings-tv3l31?file=/demo.js:397-444

Notice that even with gapMode="padding" passed, when the focus lock is open, the CSS rendered is still using margin-right:

A bit more context:

Our team could really use support for this, as unfortunately one of our major consumers has width: 100%; min-width: 100% CSS set on their body, which causes margin-right to not work as expected. We don't really have standing to tell them to remove this CSS, so the only other alternative to use padding-right instead (which works correctly with 100% width).

As a workaround we're currently grabbing the --removed-body-scroll-bar-size CSS var and manually setting padding-right, but we'd love to be able to remove this workaround.

onClickOutside doesn't prevent reopening

Hi @theKashey πŸ‘‹

I used this library on a bunch of projects, it's really great except for one small thing: onClickOutside. I struggle to make it works on mobile because it doesn't prevent the initial event.

To explain my pain, suppose that we have a Profile Button which open a profile form modal:

 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 β”‚                                                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”β”‚
 β”‚                                                 β”‚Profileβ”‚β”‚
 β”‚                                                 β””β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
 β”‚               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚
 β”‚               β”‚                          β”‚               β”‚
 β”‚               β”‚                          β”‚               β”‚
 β”‚               β”‚                          β”‚               β”‚
 β”‚               β”‚                          β”‚               β”‚
 β”‚               β”‚                          β”‚               β”‚
 β”‚               β”‚    Profile form modal    β”‚               β”‚
 β”‚               β”‚                          β”‚               β”‚
 β”‚               β”‚                          β”‚               β”‚
 β”‚               β”‚                          β”‚               β”‚
 β”‚               β”‚                          β”‚               β”‚
 β”‚               β”‚                          β”‚               β”‚
 β”‚               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚
 β”‚                                                          β”‚
 β”‚                                                          β”‚
 β”‚                                                          β”‚
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

If I choose to close my modal on click outside, it's easy, but it will not works if I click on the profile button (it will close on reopen the modal immediately).

`onClickOutside` doesn't trigger on iOS

Hi @theKashey,

Whilst implementing a modal dialog using react-focus-on I have realised that the onClickOutside callback doesn't get triggered on iOS (possibly all touch devices?)

I have done some investigation and I saw that the lib attaches a click handler on the document in Effect.tsx (here).

However, after some investigation, it appears iOS doesn't trigger any click events on nodes unless they "look" clickable (see this comment).

I have a fix for it (basically attaching a touchstart handler on top of the click handler).
I will send you a PR and we can continue the discussion there.

✌️

Scroll lock prevents multi-touch zoom and back functionality

Hi there, thanks for making this package it's really handled a lot of the situations I was manually catering for.

One issue I have with it is that I want scroll lock enabled, to prevent the page behind a modal scrolling, but I also want multi-touch zoom and swipe to go back to work. Is there currently any flags that will allow this while maintaining the scroll-lock for the rest of the page?

I have a modal inside a Portal if that's relevant to it.

Tabbing in radio buttons are broken in FocusOn

When using a radio button group inside FocusOn, keyboard tabbing is broken. When the focus is on a radio button the focus get "stuck" and doesn't move to the next element when pressing tab.

In the test case below, when the focus trap is enabled:

  • When the first radio button has focus, tabbing doesn't do anything. Shift + tab works and the focus is set to the button.

  • When the second radio button has focus, tabbing doesn't do anything. Shift + tab doesn't work either.

  • When the last radio button has focus, tabbing and shift + tab both work as expected.

Compare it to the second example with checkboxes which work correctly.

Test case

Ability to control lock/unlock with prop

Sometimes you want to be able to lock and unlock before the component has fully unmounted, e.g. when doing animations.

To illustrate my problem I've created a simple codesandbox with react-spring.

https://codesandbox.io/s/runtime-lake-76g5v

When you open the dialog everything works as expected, however when you close it you can notice a obvious delay. The focus isn't returned until the component has fully unmounted and the scroll is locked too. This behavior isn't ideal imo.

Is there some way to solve this without any API change?

How to preventDefault?

I have FocusOn up and running. When I click outside of the focused area, it's running onClickOutside and also clicking on the item in the background. Typically I'd just add something like e.preventDefault(); but that's not working. How do I get it to close FocusOn, but not also click something in the background?

console.log in sidecar

Im seeing performance logs in the latest version e.g,

initialization: 0.014999997802078724
Combination.js:7 initialization: 0.010000003385357559
Combination.js:7 initialization: 0.0050000089686363935
Combination.js:7 initialization: 0.014999997802078724
2Combination.js:7 initialization: 0.004999994416721165
2Combination.js:7 initialization: 0.004999994416721165
Combination.js:7 initialization: 0.0050000089686363935
Combination.js:7 initialization: 0.004999994416721165
Combination.js:7 initialization: 0.0050000089686363935
Combination.js:7 initialization: 0.00999998883344233

from Combination.js

import * as tslib_1 from "tslib";
import * as React from 'react';
import { FocusOn as ReactFocusOn } from "./UI";
var RequireSideCar = function (props) {
    var now = performance.now();
    var SideCar = require('./sidecar').default;
    >>>> console.log('initialization:', performance.now() - now);
    return React.createElement(SideCar, tslib_1.__assign({}, props));
};
export function FocusOn(props) {
    return (React.createElement(ReactFocusOn, tslib_1.__assign({}, props, { sideCar: RequireSideCar })));
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.