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

[Web] Add hover support #69

Closed
wants to merge 21 commits into from
Closed

[Web] Add hover support #69

wants to merge 21 commits into from

Conversation

nandorojo
Copy link
Owner

@nandorojo nandorojo commented Jan 25, 2021

In addition to the Pressable component, it would be nice to style components directly with hover styles.

Components should:

  1. Intelligently listen for hover events, if and only if there is a non-empty set of hover styles.
  2. Only capture hover events on web.
  3. Use theme values in hover styles.

API

There are two options I see here:

<View sx={{ '&:hover': { bg: 'blue' }, bg: 'green' }} />

Or

<View hovered={{ bg: 'blue' }} sx={{ bg: 'green' }} />

I think the second one perhaps looks prettier...but the first one might be more scalable. This would ideally let us have hover styles in our theme's variants, etc.

// theme.ts
export default {
  buttons: {
    primary: {
      '&:hover': {
        bg: 'blue'
      },
      bg: 'green'
    }
  }
}

I have to think about which syntax I prefer. Second seems more satisfying to use. 🤔

TODO

  • Capture hover events
  • Add SSR support
  • Add example and test
  • Inject actual hover styles logic into mapPropsToStyledComponent/css functions. This should probably be handled similar to responsiveSSRStyles. Ideally we can think of a method of doing this that would also support other pseudo elements, such as focus, in the future.
  • Publish to pseudo tag on NPM.
  • Document
  • Add support with sx prop.

All the boilerplate stateful hover logic is complete. All that's left is to construct the hoverStyles to pass when isHovered is true.

Notes

I am leaning towards not supporting responsive arrays for hover styles at first. It's just going to get really messy with the current implementation. Maybe once it all works, we can add support for this again.

@cmaycumber
Copy link
Contributor

I prefer the first approach because it gives users the ability to do more from the theme file itself otherwise the styles for hover and the logic related to the current variant have to be applied in the component code.

The biggest downside for the second one to me is handling the hover effects for a variety of variants (mostly buttons/links for me). I've noticed that when trying to apply pseudo selector like styles to components it often leads to some boilerplate/messier code.

@nandorojo
Copy link
Owner Author

I added support for both approaches, including variant support (single and multiple.)

Feel free to try out the normal example app.

@nandorojo
Copy link
Owner Author

Version 1.5.0-alpha.1 published to NPM.

yarn add dripsy@pseudo

@nandorojo
Copy link
Owner Author

@nandorojo
Copy link
Owner Author

I'll test this in my app more tomorrow and merge to master. Based on my usage in the example app, it all works smoothly, so it should be good to go.

I'll probably employ the same strategy in my animation library to add hover support.

@cmaycumber
Copy link
Contributor

This is 🔥 . I'll use it as soon as it gets merged in!

@nandorojo
Copy link
Owner Author

Sounds good. Mind trying it out with yarn add dripsy@pseudo? All seems to be working well to me.

@nandorojo
Copy link
Owner Author

I think there might be a bug where it's re-rendering on hovers, even when there are no hover styles specified. Once I fix that, it'll be good to go.

@cmaycumber
Copy link
Contributor

Sounds good. Mind trying it out with yarn add dripsy@pseudo? All seems to be working well to me.

Yeah, will do.

@nandorojo
Copy link
Owner Author

Just fixed that, silly bug, forgot the word return here.

@nandorojo
Copy link
Owner Author

nandorojo commented Jan 26, 2021

1.5.0-alpha.2 published to NPM.

@nandorojo
Copy link
Owner Author

Looks like this is causing a few style issues for me in my real app. I'll have to debug further. At first glance, it seems like padding and align items/self are experiencing weird behavior. I wonder if this is due to a change in the order in mapPropsToStyledComponent. I'll have to test more closely, but this is likely the culprit.

@cmaycumber
Copy link
Contributor

Does this need to be ported into #74?

I can help debug this as well.

@nandorojo
Copy link
Owner Author

Yeah probably, the one issue is that it has a bug I haven't been able to identify yet. Ideally it would point at that PR, but still be a separate branch until we figure out that bug.

@nandorojo
Copy link
Owner Author

@cmaycumber Now that #74 is merged, I might take another stab at getting this to work in core. Hard to say what was going wrong with it exactly, it just made some styles apply incorrectly.

@nandorojo
Copy link
Owner Author

One thought to consider: I've gotten very into the style of doing this:

<Press>
  {({ hovered }) => <MotiView animate={{ scale: hovered ? 1.1 : 1 }} />}
</Press>

Honestly, I think encouraging this API might be better. Hover interactions are probably best with 2 conditions:

  • The interaction should be trapped by a parent, not the element that's actually animating. In the example above, if you scaled the actual element that captured hovered events, then hovering on the edges would flicker. This wouldn't be desirable.
  • Most hover interactions will want some animation tied to it. Moti is the only way I know of to have parity with such animations across platforms. So I think I'm going to abandon this PR, in favor of the API used above.

@nandorojo nandorojo closed this Mar 28, 2021
@cmaycumber
Copy link
Contributor

One thought to consider: I've gotten very into the style of doing this:

<Press>
  {({ hovered }) => <MotiView animate={{ scale: hovered ? 1.1 : 1 }} />}
</Press>

Honestly, I think encouraging this API might be better. Hover interactions are probably best with 2 conditions:

  • The interaction should be trapped by a parent, not the element that's actually animating. In the example above, if you scaled the actual element that captured hovered events, then hovering on the edges would flicker. This wouldn't be desirable.
  • Most hover interactions will want some animation tied to it. Moti is the only way I know of to have parity with such animations across platforms. So I think I'm going to abandon this PR, in favor of the API used above.

I agree with this. That's alright with me, I've started using moti in most of my applications. I think there's probably a way to use this strategy and still make a hover effect themeable from the theme file.

@nandorojo nandorojo mentioned this pull request Apr 15, 2021
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.

2 participants