diff --git a/packages/docs-gesture-handler/docs/components/buttons.mdx b/packages/docs-gesture-handler/docs/components/buttons.mdx index 041d387fbe..7b895a26f5 100644 --- a/packages/docs-gesture-handler/docs/components/buttons.mdx +++ b/packages/docs-gesture-handler/docs/components/buttons.mdx @@ -9,6 +9,10 @@ import GifGallery from '@site/components/GifGallery'; 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. +::: + diff --git a/packages/docs-gesture-handler/docs/components/clickable.mdx b/packages/docs-gesture-handler/docs/components/clickable.mdx new file mode 100644 index 0000000000..3983be883d --- /dev/null +++ b/packages/docs-gesture-handler/docs/components/clickable.mdx @@ -0,0 +1,275 @@ +--- +id: clickable +title: Clickable +sidebar_label: Clickable +--- + +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. + +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). + +## Replacing old buttons + +If you were using `RectButton`, or `BorderlessButton` in your app, you can easily replace them with `Clickable`. Check out full code in [example](#example) section below. + +### RectButton + +To replace `RectButton` with `Clickable`, simply add `underlayActiveOpacity={0.105}` to your `Clickable` component. This will animate the underlay when the button is pressed. + +```tsx + +``` + +### BorderlessButton + +Replacing `BorderlessButton` with `Clickable` is as easy as replacing `RectButton`. Just add `activeOpacity={0.3}` to your `Clickable` component. This will animate the whole component when the button is pressed. + +```tsx + +``` + +## Example + +In this example we will demonstrate how to recreate `RectButton` and `BorderlessButton` effects using `Clickable` component. + + + { + console.log('BaseButton built with Clickable'); + }} + style={[styles.button, { backgroundColor: '#7d63d9' }]}> + BaseButton + + + { + console.log('RectButton built with Clickable'); + }} + style={[styles.button, { backgroundColor: '#4f9a84' }]} + underlayActiveOpacity={0.105}> + RectButton + + + { + console.log('BorderlessButton built with Clickable'); + }} + style={[styles.button, { backgroundColor: '#5f97c8' }]} + activeOpacity={0.3}> + BorderlessButton + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + + gap: 20, + }, + button: { + width: 200, + height: 70, + borderRadius: 15, + alignItems: 'center', + justifyContent: 'center', + }, + buttonText: { + color: 'white', + fontSize: 14, + fontWeight: '600', + }, +}); +`}/> + + +## Properties + +### exclusive + +```ts +exclusive?: boolean; +``` + +Defines if more than one button could be pressed simultaneously. By default set to `true`. + + +### touchSoundDisabled + + +```ts +touchSoundDisabled?: boolean; +``` + +If set to `true`, the system will not play a sound when the button is pressed. + +### onPressIn + +) => void; + +type GestureEvent = { + handlerTag: number; + numberOfPointers: number; + pointerType: PointerType; + pointerInside: boolean; +} + +enum PointerType { + TOUCH, + STYLUS, + MOUSE, + KEY, + OTHER, +} +`}/> + +Triggered when the button gets pressed (analogous to `onPressIn` in `TouchableHighlight` from RN core). + +### onPressOut + +) => void; + +type GestureEvent = { + handlerTag: number; + numberOfPointers: number; + pointerType: PointerType; + pointerInside: boolean; +} + +enum PointerType { + TOUCH, + STYLUS, + MOUSE, + KEY, + OTHER, +} +`}/> + +Triggered when the button gets released (analogous to `onPressOut` in `TouchableHighlight` from RN core). + +### onPress + +```ts +onPress?: (pointerInside: boolean) => void; +``` + +Triggered when the button gets pressed (analogous to `onPress` in `TouchableHighlight` from RN core). + +### onLongPress + +```ts +onLongPress?: () => void; +``` + +Triggered when the button gets pressed for at least [`delayLongPress`](#delaylongpress) milliseconds. + + +### onActiveStateChange + +```ts +onActiveStateChange?: (active: boolean) => void; +``` + +Triggered when the button transitions between active and inactive states. It passes the current active state as a boolean variable to the method as the first parameter. + +### delayLongPress + +```ts +delayLongPress?: number; +``` + +Defines the delay, in milliseconds, after which the [`onLongPress`](#onlongpress) callback gets called. By default set to `600`. + +### underlayColor + +```ts +underlayColor?: string; +``` + +Background color of underlay. This only takes effect when `underlayActiveOpacity` is set. + +### underlayActiveOpacity + +```ts +underlayActiveOpacity?: number; +``` + +Defines the opacity of underlay when the button is active. If not set, underlay won't be rendered. + +### activeOpacity + +```ts +activeOpacity?: number; +``` + +Defines the opacity of the whole component when the button is active. + +### underlayInitialOpacity + +```ts +underlayInitialOpacity?: number; +``` + +Defines the initial opacity of underlay when the button is inactive. By default set to `0`. + +### initialOpacity + +```ts +initialOpacity?: number; +``` + +Defines the initial opacity of the whole component when the button is inactive. By default set to `1` + + +### androidRipple + + + + +Configuration for the ripple effect on Android. If not provided, the ripple effect will be disabled. If `{}` is provided, the ripple effect will be enabled with default configuration. diff --git a/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx b/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx index e5b0812531..fe0fa85d3a 100644 --- a/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx +++ b/packages/docs-gesture-handler/docs/guides/upgrading-to-3.mdx @@ -246,7 +246,15 @@ code2={ ### Buttons -The implementation of buttons has been updated, resolving most button-related issues. They have also been internally rewritten to utilize the new hook API. The original button components are still accessible but have been renamed with the prefix `Legacy`, e.g., `RectButton` is now available as `LegacyRectButton`. +RNGH3 introduces the [`Clickable`](/docs/components/clickable) component — a flexible, unified replacement for all previous button types. While `Clickable` shares the same logic as our standard buttons, it offers a more customizable API. + +To help you migrate, here is the current state of our button components: + +- [`Clickable`](/docs/components/clickable) - The recommended component. + +- Standard Buttons (Deprecated) - `BaseButton`, `RectButton` and `BorderlessButton` are still available but are now deprecated. They have been internally rewritten using the new Hooks API to resolve long-standing issues. + +- Legacy Buttons (Deprecated): The original, pre-rewrite versions are still accessible, but have been renamed with a `Legacy` prefix (e.g., `LegacyRectButton`). Although the legacy JS implementation of the buttons is still available, they also use the new host component internally. Because of that, `PureNativeButton` is no longer available in Gesture Handler 3. diff --git a/skills/gesture-handler-3-migration/SKILL.md b/skills/gesture-handler-3-migration/SKILL.md index 888238fe2e..63f1bf94c9 100644 --- a/skills/gesture-handler-3-migration/SKILL.md +++ b/skills/gesture-handler-3-migration/SKILL.md @@ -169,6 +169,8 @@ The implementation of buttons has been updated, resolving most button-related is `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}`. + Other components have also been internally rewritten using the new hook API but are exported under their original names, so no changes are necessary on your part. However, if you need to use the previous implementation for any reason, the legacy components are also available and are prefixed with `Legacy`, e.g., `ScrollView` is now available as `LegacyScrollView`. Rename all instances of createNativeWrapper to legacy_createNativeWrapper. This includes both the import statements and the function calls.