Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add event touch hit target hit slop logic to experimental event API #15261

Closed
wants to merge 16 commits into from

Conversation

trueadm
Copy link
Contributor

@trueadm trueadm commented Mar 29, 2019

Note: this is for an experimental event API that we're testing out internally at Facebook.

This PR adds the necessary logic to mount and update the hit slop for touch hit targets. It does this by creating an element, absolutely positioning it inside a child and then appending it the target DOM element. This required moving some parts around to add the necessary fields required to properly ensure that we can create the element in the right namespace. There are also some TODOs that will be tackled in the coming weeks.

@sizebot
Copy link

sizebot commented Mar 29, 2019

ReactDOM: size: 0.0%, gzip: 🔺+0.1%

Details of bundled changes.

Comparing: 4482fdd...15f37f3

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.development.js +0.5% +0.5% 814.12 KB 818.46 KB 184.32 KB 185.18 KB UMD_DEV
react-dom.production.min.js 0.0% 🔺+0.1% 105.15 KB 105.2 KB 33.98 KB 34.01 KB UMD_PROD
react-dom.profiling.min.js 0.0% 0.0% 108.13 KB 108.18 KB 34.62 KB 34.63 KB UMD_PROFILING
react-dom.development.js +0.5% +0.5% 808.51 KB 812.85 KB 182.73 KB 183.58 KB NODE_DEV
react-dom.production.min.js 0.0% 🔺+0.1% 105.13 KB 105.17 KB 33.48 KB 33.5 KB NODE_PROD
react-dom.profiling.min.js 0.0% +0.1% 108.23 KB 108.27 KB 34.09 KB 34.11 KB NODE_PROFILING
ReactDOM-dev.js +0.6% +0.5% 833.25 KB 838.05 KB 184.37 KB 185.32 KB FB_WWW_DEV
ReactDOM-prod.js 🔺+1.6% 🔺+1.1% 331.56 KB 336.78 KB 61.06 KB 61.74 KB FB_WWW_PROD
ReactDOM-profiling.js +2.6% +2.2% 337.95 KB 346.76 KB 62.41 KB 63.77 KB FB_WWW_PROFILING
react-dom-unstable-fire.development.js +0.5% +0.5% 814.47 KB 818.8 KB 184.47 KB 185.35 KB UMD_DEV
react-dom-unstable-fire.production.min.js 0.0% 🔺+0.1% 105.17 KB 105.21 KB 33.99 KB 34.02 KB UMD_PROD
react-dom-unstable-fire.profiling.min.js 0.0% 0.0% 108.14 KB 108.19 KB 34.62 KB 34.64 KB UMD_PROFILING
react-dom-unstable-fire.development.js +0.5% +0.5% 808.85 KB 813.19 KB 182.86 KB 183.74 KB NODE_DEV
react-dom-unstable-fire.production.min.js 0.0% 🔺+0.1% 105.14 KB 105.18 KB 33.49 KB 33.51 KB NODE_PROD
react-dom-unstable-fire.profiling.min.js 0.0% +0.1% 108.24 KB 108.29 KB 34.09 KB 34.12 KB NODE_PROFILING
ReactFire-dev.js +0.6% +0.5% 832.46 KB 837.26 KB 184.29 KB 185.26 KB FB_WWW_DEV
ReactFire-prod.js 🔺+1.6% 🔺+1.2% 320.22 KB 325.45 KB 58.73 KB 59.41 KB FB_WWW_PROD
ReactFire-profiling.js +2.7% +2.1% 326.55 KB 335.27 KB 60.08 KB 61.34 KB FB_WWW_PROFILING
react-dom-test-utils.development.js 0.0% 0.0% 47.49 KB 47.49 KB 12.98 KB 12.98 KB UMD_DEV
react-dom-test-utils.production.min.js 0.0% 🔺+0.1% 9.95 KB 9.95 KB 3.65 KB 3.66 KB UMD_PROD
react-dom-test-utils.development.js 0.0% 0.0% 47.21 KB 47.21 KB 12.91 KB 12.91 KB NODE_DEV
react-dom-test-utils.production.min.js 0.0% 0.0% 9.73 KB 9.73 KB 3.58 KB 3.59 KB NODE_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 60.41 KB 60.41 KB 15.71 KB 15.72 KB NODE_DEV
react-dom-server.browser.development.js 0.0% 0.0% 130.91 KB 130.91 KB 34.57 KB 34.57 KB NODE_DEV
ReactDOMServer-dev.js 0.0% 0.0% 133.22 KB 133.22 KB 34.32 KB 34.32 KB FB_WWW_DEV
ReactDOMServer-prod.js 0.0% -0.0% 46.19 KB 46.19 KB 10.63 KB 10.63 KB FB_WWW_PROD
react-dom-server.node.development.js 0.0% 0.0% 132.86 KB 132.86 KB 35.12 KB 35.12 KB NODE_DEV
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.1% 1.21 KB 1.21 KB 705 B 706 B UMD_PROD
react-dom-unstable-fizz.browser.development.js 0.0% +0.1% 3.49 KB 3.49 KB 1.41 KB 1.41 KB NODE_DEV
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.2% 1.05 KB 1.05 KB 636 B 637 B NODE_PROD
react-dom-unstable-fizz.node.development.js 0.0% +0.1% 3.74 KB 3.74 KB 1.43 KB 1.43 KB NODE_DEV
react-dom-unstable-fizz.node.production.min.js 0.0% 🔺+0.2% 1.1 KB 1.1 KB 666 B 667 B NODE_PROD

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-test-renderer.development.js +0.1% +0.1% 509.78 KB 510.11 KB 107.26 KB 107.32 KB UMD_DEV
react-test-renderer.production.min.js 0.0% 0.0% 62.79 KB 62.79 KB 19.14 KB 19.14 KB UMD_PROD
react-test-renderer.development.js +0.1% +0.1% 505.3 KB 505.62 KB 106.11 KB 106.17 KB NODE_DEV
react-test-renderer.production.min.js 0.0% 0.0% 62.48 KB 62.48 KB 18.97 KB 18.97 KB NODE_PROD
ReactTestRenderer-dev.js +0.1% +0.1% 516.46 KB 516.86 KB 105.87 KB 105.94 KB FB_WWW_DEV
react-test-renderer-shallow.development.js 0.0% -0.0% 38.98 KB 38.98 KB 9.81 KB 9.81 KB UMD_DEV
react-test-renderer-shallow.development.js 0.0% 0.0% 33.2 KB 33.2 KB 8.41 KB 8.41 KB NODE_DEV

Generated by 🚫 dangerJS

@necolas necolas mentioned this pull request Mar 29, 2019
// element inside it absolutely position around the target.
// TODO add a dev check for the computed style and warn if it isn't
// compatible.
element.style.position = 'relative';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@necolas We need to come up with a good solution for this. We should mark this in the umbrella issue and track it as to how we can validate it and make sure stacking order etc is good.

Copy link
Collaborator

@sebmarkbage sebmarkbage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this going to work with server rendering? Right now you're not creating the equivalent node during the server render and it won't patch it up during hydration.

Copy link
Collaborator

@sebmarkbage sebmarkbage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our insertBefore logic etc won't account for this extra element so it's possible that with updates, we end up creating an invalid DOM.

// We update the event target state node to be that of the element.
// We can then diff this entry to determine if we need to add the
// hit slop element, or change the dimensions of the hit slop.
const lastElement = internalInstanceHandle.stateNode;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't drill into fibers at this level. We assume that host configs don't have access to fibers. These are supposed to be opaque types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't aware of this constraint. I can re-work it so that stateNode is an object ref instead. Then the object ref is passed to this function in host config; would that make more sense?

@trueadm
Copy link
Contributor Author

trueadm commented Apr 1, 2019

@sebmarkbage In regards to SSR, there is a task on here #15257 to do it as a separate point.

In regards to insertBefore, why wouldn't that work?

// element inside it absolutely position around the target.
// TODO add a dev check for the computed style and warn if it isn't
// compatible.
element.style.position = 'relative';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't be resilient to the styles changing on the element. Updates to it might override this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this was a bit talking point with @necolas too. There's no cheap way to get around having to do a computed lookup to find what the position is. Do you have any ideas on how we might solve this problem?

'div',
emptyObject,
rootContainerInstance,
parentNamespace,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work if the parentNamespace isn't HTML so you should throw if you don't intend to support other namespaces.

@sebmarkbage
Copy link
Collaborator

If the EventTarget's element gets a child added at the end, then React will think it's the last child so we use parentNode.appendChild(newNode) to insert it. That will put it at the end of the list but I think you want the hit slop to always be the last child in the children list.

<EventTarget>
  <div>
    Hi
    {c ? <span>I will be after the hit slop</span> : null}
  </div>
</EventTarget>

Can you add this test?

@trueadm
Copy link
Contributor Author

trueadm commented Apr 1, 2019

@sebmarkbage As the hit slop is absolutely positioned, I'm not sure it matters. It might mess with CSS styles though. With your idea around <EventTarget> being a child of the <div> how would it work?

@trueadm
Copy link
Contributor Author

trueadm commented Apr 2, 2019

I'm closing this and will open another PR with a different implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants