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

[0.73-stable] Add mouse hover events to RCTTextView #2143

Conversation

amgleitman
Copy link
Member

@amgleitman amgleitman commented Jun 25, 2024

Summary:

We have a feature request to allow mouse hover events for subelements inside a Text element. This builds off #2137 to get things all set.

For now we're only pushing this into 0.73-stable because we want to take more time to consider the native-side architecture for 0.74 onwards.

One slight drawback is that this only works completely properly when there is only one level of onMouseEnter events underneath the main box. For example, if we move the mouse from red to blue in the below example, we see a "leave red" event immediately before an "enter blue" event. The reason for this is that at the native level, all RCTVirtualTextViews that represent internal Text nodes are direct children of the parent RCTTextView instead of directly reflecting the DOM hierarchy. This can potentially be fixed by replacing the superview calls inside updateHoveredSubviewWithEvent: with something more appropriate, but this is still sufficient for our needs, so I think it's passable as a first iteration of this PR.

Test Plan:

Validated using the following example in RNTester:

{
  title: 'Transparent Background Color',
  render: function (): React.Node {
    const rootProps = {
      onMouseEnter: _ => console.log('Mouse enter gray'),
      onMouseLeave: _ => console.log('Mouse leave gray'),
    };

    return (
      <View style={{backgroundColor: '#00000020'}}>
        <Text {...rootProps}>
          Text in a gray box!
          <Text
            style={{color: 'red'}}
            onMouseEnter={_ => console.log('Mouse enter red')}
            onMouseLeave={_ => console.log('Mouse leave red')}>
            Another text in a (inline) red box (which is
            <Text
              style={{color: 'blue'}}
              onMouseEnter={_ => console.log('Mouse enter blue')}
              onMouseLeave={_ => console.log('Mouse leave blue')}>
              inside
            </Text>
            the gray box).
          </Text>
        </Text>
      </View>
    );
  },
}

@amgleitman amgleitman requested a review from a team as a code owner June 25, 2024 18:16
Copy link

@PPatBoyd PPatBoyd left a comment

Choose a reason for hiding this comment

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

It would be good to resolve if we can deterministically create a non-duplicate list of descendantViewTags without relying on throwing away duplicates through a Set, but otherwise this change looks good to me :)

@amgleitman
Copy link
Member Author

It would be good to resolve if we can deterministically create a non-duplicate list of descendantViewTags without relying on throwing away duplicates through a Set, but otherwise this change looks good to me :)

We're now providing the virtual text subviews in a separate array, so this is no longer an issue.

@amgleitman amgleitman enabled auto-merge (squash) June 28, 2024 23:12
@amgleitman amgleitman merged commit a08aa42 into microsoft:0.73-stable Jul 10, 2024
14 checks passed
@amgleitman amgleitman deleted the 0.73-text-children-mouse-hover-events branch July 10, 2024 00:08
amgleitman added a commit to amgleitman/react-native-macos that referenced this pull request Jul 25, 2024
* Initial implementation

* Refactor and dedupe some code

* Basic error handling

* Clarify comment about mousemove order

* Cleanup: enumerate all text attributes at once instead of doing multiple passes

* Use *shadow* view traversal for handling nested mouse events

* Remove potentially confusing comment

* descendantViewTags doesn't need to worry about duplicates

* Distinguish between embedded views and virtual text subviews

* Scope _virtualSubviews to macOS only

* nit: use separate #if blocks for `setTextStorage:...` and `getRectForCharRange:` inclusions

* TARGET_OS_OSX blocks for virtualSubviewTags

* Remove #if TARGET_OS_OSX blocks, since these changes are potentially upstreamable

* Clarify a TODO

---------

Co-authored-by: Adam Gleitman <adgleitm@microsoft.com>
amgleitman added a commit that referenced this pull request Jul 27, 2024
…able) (#2149)

* [0.73-stable] New events for RCTUIView (#2137)

* Move mouse events from RCTView to superclass RCTUIView

* Add focus and responder events

* Move mouse event implementations to RCTUIView class

---------

Co-authored-by: Adam Gleitman <adgleitm@microsoft.com>

* [0.73-stable] Add mouse hover events to `RCTTextView` (#2143)

* Initial implementation

* Refactor and dedupe some code

* Basic error handling

* Clarify comment about mousemove order

* Cleanup: enumerate all text attributes at once instead of doing multiple passes

* Use *shadow* view traversal for handling nested mouse events

* Remove potentially confusing comment

* descendantViewTags doesn't need to worry about duplicates

* Distinguish between embedded views and virtual text subviews

* Scope _virtualSubviews to macOS only

* nit: use separate #if blocks for `setTextStorage:...` and `getRectForCharRange:` inclusions

* TARGET_OS_OSX blocks for virtualSubviewTags

* Remove #if TARGET_OS_OSX blocks, since these changes are potentially upstreamable

* Clarify a TODO

---------

Co-authored-by: Adam Gleitman <adgleitm@microsoft.com>

* Add an example for Text mouse hover events

* Add missing macOS props to Text.d.ts

* Fix flow errors

* Fix lint errors

---------

Co-authored-by: Adam Gleitman <adgleitm@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants