Conversation
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…native-gesture-handler into @mbert/clickable
…lickable component
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import HeaderWithBadges from '@site/src/components/HeaderWithBadges'; | ||
|
|
||
| :::danger | ||
| Button components described in this section are deprecated and will be removed in the future. Please use [`Clickable`](/docs/components/clickable) instead. |
There was a problem hiding this comment.
Actually, maybe we would like to keep RawButton? This would keep more flexibility for advanced users. But that's just a thought, not strong opinion - I'm not sure if we want to do that (cc @j-piasecki, @akwasniewski)
There was a problem hiding this comment.
I'm not sure there's a need for that. Isn't it basically a Clickable without predefined event handlers (so no onPress and onLongPress)?
## Description This PR introduces new `Clickable` component, which is meant to be a replacement for buttons. > [!NOTE] > Docs for `Clickable` will be added in #4022, as I don't want to release them right away after merging this PR. ### `borderless` For now, `borderless` doesn't work. I've tested clickable with some changes that allow `borderless` ripple to be visible, however we don't want to introduce them here because it would break other things. Also it should be generl fix, not in the PR with new component. ## Stress test Render list with 2000 buttons 25 times (50ms delay between renders), drop 3 best and 3 worst results. Then calculate average. Stress test example is available in this PR. #### Android | | $t_{Button}$ | $t_{Clickable}$ | $\Delta{t}$ | |------------------|--------------|-----------------|--------------| | `BaseButton` | 1196,18 | 1292,3 | 96,12 | | `RectButton` | 1672,6 | 1275,68 | -396,92 | | `BorderlessButton` | 1451,34 | 1290,74 | -160,6 | #### iOS | | $t_{Button}$ | $t_{Clickable}$ | $\Delta{t}$ | |------------------|--------------|-----------------|--------------| | `BaseButton` | 1101,37 | 1154,6 | 53,23 | | `RectButton` | 1528,07 | 1160,07 | -368 | | `BorderlessButton` | 1330,24 | 1172,69 | -157,55 | #### Web | | $t_{Button}$ | $t_{Clickable}$ | $\Delta{t}$ | |------------------|--------------|-----------------|--------------| | `BaseButton` | 64,18 | 95,57 | 31,39 | | `RectButton` | 104,58 | 97,95 | -6,63 | | `BorderlessButton` | 81,11 | 98,64 | 17,53 | ## Test plan New examples --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| import HeaderWithBadges from '@site/src/components/HeaderWithBadges'; | ||
|
|
||
| :::danger | ||
| Button components described in this section are deprecated and will be removed in the future. Please use [`Clickable`](/docs/components/clickable) instead. |
There was a problem hiding this comment.
I'm not sure there's a need for that. Isn't it basically a Clickable without predefined event handlers (so no onPress and onLongPress)?
|
|
||
| `PureNativeButton` has been removed. If encountered, inform the user that it has been removed and let them decide how to handle that case. They can achieve similar functionality with other buttons. | ||
|
|
||
| When migrating buttons, you should use `Clickable` component instead. To replace `BaseButton` use `Clickable` with default props, to replace `RectButton` use `Clickable` with `underlayActiveOpacity={0.105}` and to replace `BorderlessButton` use `Clickable` with `activeOpacity={0.3}`. |
There was a problem hiding this comment.
It may also be worth adding how to replace deprecated Touchables with the new component.
|
|
||
| To help you migrate, here is the current state of our button components: | ||
|
|
||
| - [`Clickable`](/docs/components/clickable) - The recommended component. |
There was a problem hiding this comment.
It may be useful to mention the relevant configurations on how to replace other buttons/touchables. I'm sure there will be at least a dozen people reading this instead of asking an LLM.
|
|
||
| import HeaderWithBadges from '@site/src/components/HeaderWithBadges'; | ||
|
|
||
| `Clickable` is a versatile new component introduced in Gesture Handler 3 to succeed previous button implementations. Designed for maximum flexibility, it provides a highly customizable interface for native touch handling while ensuring consistent behavior across platforms. |
There was a problem hiding this comment.
| `Clickable` is a versatile new component introduced in Gesture Handler 3 to succeed previous button implementations. Designed for maximum flexibility, it provides a highly customizable interface for native touch handling while ensuring consistent behavior across platforms. | |
| `Clickable` is a versatile new component introduced in Gesture Handler 3 to supersede previous button implementations. Designed for maximum flexibility, it provides a highly customizable interface for native touch handling while ensuring consistent behavior across platforms. |
|
|
||
| `Clickable` is a versatile new component introduced in Gesture Handler 3 to succeed previous button implementations. Designed for maximum flexibility, it provides a highly customizable interface for native touch handling while ensuring consistent behavior across platforms. | ||
|
|
||
| With `Clickable`, you have more control over animations. It is possible to choose between animating the entire component or just the underlay, along with specifying desired `opacity` values. This allows you to effortlessly replicate both `RectButton` and `BorderlessButton` effects using a single unified component. Furthermore, it resolves many legacy issues found in earlier versions. On Android, you can opt for the native ripple effect or leverage JS-based animations via the [Animated API](https://reactnative.dev/docs/animated). |
There was a problem hiding this comment.
| With `Clickable`, you have more control over animations. It is possible to choose between animating the entire component or just the underlay, along with specifying desired `opacity` values. This allows you to effortlessly replicate both `RectButton` and `BorderlessButton` effects using a single unified component. Furthermore, it resolves many legacy issues found in earlier versions. On Android, you can opt for the native ripple effect or leverage JS-based animations via the [Animated API](https://reactnative.dev/docs/animated). | |
| `Clickable` provides a simple interface for the common animations like opacity, underlay, and scale, implemented entirely on the platform. On Android, it also exposes the native ripple effect on press (turned off by default). | |
| If the provided animations are not sufficient, it's possible to use `Clickable` to create fully custom interactions using either [Reanimated](https://docs.swmansion.com/react-native-reanimated/) or [Animated API](https://reactnative.dev/docs/animated). |
| } | ||
| `}/> | ||
|
|
||
| Triggered when the button gets released (analogous to `onPressOut` in `TouchableHighlight` from RN core). |
There was a problem hiding this comment.
| Triggered when the button gets released (analogous to `onPressOut` in `TouchableHighlight` from RN core). | |
| Triggered when the button gets released or the pointer moves outside of the button area (analogous to `onPressOut` in `Pressable` from RN core). |
| onPress?: (pointerInside: boolean) => void; | ||
| ``` | ||
|
|
||
| Triggered when the button gets pressed (analogous to `onPress` in `TouchableHighlight` from RN core). |
There was a problem hiding this comment.
| Triggered when the button gets pressed (analogous to `onPress` in `TouchableHighlight` from RN core). | |
| Triggered when the button gets pressed (analogous to `onPress` in `Pressable` from RN core). |
| underlayColor?: string; | ||
| ``` | ||
|
|
||
| Background color of underlay. This only takes effect when `activeUnderlayOpacity` is set. |
There was a problem hiding this comment.
| Background color of underlay. This only takes effect when `activeUnderlayOpacity` is set. | |
| Background color of the underlay. This only takes effect when `activeUnderlayOpacity` or `defaultUnderlayOpacity` is set. |
| activeUnderlayOpacity?: number; | ||
| ``` | ||
|
|
||
| Defines the opacity of underlay when the button is active. If not set, underlay won't be rendered. |
There was a problem hiding this comment.
| Defines the opacity of underlay when the button is active. If not set, underlay won't be rendered. | |
| Defines the opacity of the underlay when the button is active. By default set to `0`. |
| activeOpacity?: number; | ||
| ``` | ||
|
|
||
| Defines the opacity of the whole component when the button is active. |
There was a problem hiding this comment.
| Defines the opacity of the whole component when the button is active. | |
| Defines the opacity of the whole component when the button is active. By default set to `1`. |
Description
This PR adds docs for
ClickablecomponentTest plan
Read docs 🤓