|
| 1 | +--- |
| 2 | +id: clickable |
| 3 | +title: Clickable |
| 4 | +sidebar_label: Clickable |
| 5 | +--- |
| 6 | + |
| 7 | +import HeaderWithBadges from '@site/src/components/HeaderWithBadges'; |
| 8 | + |
| 9 | +`Clickable` is a new component introduced in Gesture Handler 3, designed to replace the previous button components. It provides a more flexible and customizable way to create buttons with native touch handling. |
| 10 | + |
| 11 | +With `Clickable`, you can decide whether to animate whole component, or just the underlay. This allows to easily recreate both `RectButton` and `BorderlessButton` effects with the same component. |
| 12 | + |
| 13 | +It also provides consistent behavior across platforms, and resolves most of the button-related issues that were present in previous versions. On android, you can decide whether to use native ripple effect, or JS based animation with Animated API |
| 14 | + |
| 15 | +## Replacing old buttons |
| 16 | + |
| 17 | +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. |
| 18 | + |
| 19 | +### RectButton |
| 20 | + |
| 21 | +To replace `RectButton` with `Clickable`, simply add `underlayActiveOpacity={0.105}` to your `Clickable` component. This will animate the underlay when the button is pressed. |
| 22 | + |
| 23 | +```tsx |
| 24 | +<Clickable |
| 25 | + ... |
| 26 | + underlayActiveOpacity={0.105}/> |
| 27 | +``` |
| 28 | + |
| 29 | +### BorderlessButton |
| 30 | + |
| 31 | +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. |
| 32 | + |
| 33 | +```tsx |
| 34 | +<Clickable |
| 35 | + ... |
| 36 | + activeOpacity={0.3}/> |
| 37 | +``` |
| 38 | + |
| 39 | +## Example |
| 40 | + |
| 41 | +In this example we will demonstrate how to recreate `RectButton` and `BorderlessButton` effects using `Clickable` component. |
| 42 | + |
| 43 | +<CollapsibleCode |
| 44 | +label="Show full example" |
| 45 | +expandedLabel="Hide full example" |
| 46 | +lineBounds={[7, 40]} |
| 47 | +src={` |
| 48 | +import React from 'react'; |
| 49 | +import { StyleSheet, Text } from 'react-native'; |
| 50 | +import { |
| 51 | + GestureHandlerRootView, |
| 52 | + Clickable, |
| 53 | +} from 'react-native-gesture-handler'; |
| 54 | +
|
| 55 | +export default function ClickableExample() { |
| 56 | + return ( |
| 57 | + <GestureHandlerRootView style={styles.container}> |
| 58 | + <Clickable |
| 59 | + onPress={() => { |
| 60 | + console.log('BaseButton built with Clickable'); |
| 61 | + }} |
| 62 | + style={[styles.button, { backgroundColor: '#7d63d9' }]}> |
| 63 | + <Text style={styles.buttonText}>BaseButton</Text> |
| 64 | + </Clickable> |
| 65 | +
|
| 66 | + <Clickable |
| 67 | + onPress={() => { |
| 68 | + console.log('RectButton built with Clickable'); |
| 69 | + }} |
| 70 | + style={[styles.button, { backgroundColor: '#4f9a84' }]} |
| 71 | + underlayActiveOpacity={0.105}> |
| 72 | + <Text style={styles.buttonText}>RectButton</Text> |
| 73 | + </Clickable> |
| 74 | +
|
| 75 | + <Clickable |
| 76 | + onPress={() => { |
| 77 | + console.log('BorderlessButton built with Clickable'); |
| 78 | + }} |
| 79 | + style={[styles.button, { backgroundColor: '#5f97c8' }]} |
| 80 | + activeOpacity={0.3}> |
| 81 | + <Text style={styles.buttonText}>BorderlessButton</Text> |
| 82 | + </Clickable> |
| 83 | + </GestureHandlerRootView> |
| 84 | + ); |
| 85 | +} |
| 86 | +
|
| 87 | +const styles = StyleSheet.create({ |
| 88 | + container: { |
| 89 | + flex: 1, |
| 90 | + alignItems: 'center', |
| 91 | + justifyContent: 'center', |
| 92 | +
|
| 93 | + gap: 20, |
| 94 | + }, |
| 95 | + button: { |
| 96 | + width: 200, |
| 97 | + height: 70, |
| 98 | + borderRadius: 15, |
| 99 | + alignItems: 'center', |
| 100 | + justifyContent: 'center', |
| 101 | + }, |
| 102 | + buttonText: { |
| 103 | + color: 'white', |
| 104 | + fontSize: 14, |
| 105 | + fontWeight: '600', |
| 106 | + }, |
| 107 | +}); |
| 108 | +`}/> |
| 109 | + |
| 110 | + |
| 111 | +## Properties |
| 112 | + |
| 113 | +### exclusive |
| 114 | + |
| 115 | +```ts |
| 116 | +exclusive?: boolean; |
| 117 | +``` |
| 118 | + |
| 119 | +Defines if more than one button could be pressed simultaneously. By default set to `true`. |
| 120 | + |
| 121 | +<HeaderWithBadges platforms={['android']}> |
| 122 | +### touchSoundDisabled |
| 123 | +</HeaderWithBadges> |
| 124 | + |
| 125 | +```ts |
| 126 | +touchSoundDisabled?: boolean; |
| 127 | +``` |
| 128 | + |
| 129 | +If set to `true`, the system will not play a sound when the button is pressed. |
| 130 | + |
| 131 | +### onPressIn |
| 132 | + |
| 133 | +```ts |
| 134 | +onPressIn?: (pointerInside: boolean) => void; |
| 135 | +``` |
| 136 | + |
| 137 | +Triggered when the button gets pressed (analogous to `onPressIn` in `TouchableHighlight` from RN core). |
| 138 | + |
| 139 | +### onPressOut |
| 140 | + |
| 141 | +```ts |
| 142 | +onPressOut?: (pointerInside: boolean) => void; |
| 143 | +``` |
| 144 | + |
| 145 | +Triggered when the button gets released (analogous to `onPressOut` in `TouchableHighlight` from RN core). |
| 146 | + |
| 147 | +### onPress |
| 148 | + |
| 149 | +```ts |
| 150 | +onPress?: (pointerInside: boolean) => void; |
| 151 | +``` |
| 152 | + |
| 153 | +Triggered when the button gets pressed (analogous to `onPress` in `TouchableHighlight` from RN core). |
| 154 | + |
| 155 | +### onLongPress |
| 156 | + |
| 157 | +```ts |
| 158 | +onLongPress?: () => void; |
| 159 | +``` |
| 160 | + |
| 161 | +Triggered when the button gets pressed for at least [`delayLongPress`](#delaylongpress) milliseconds. |
| 162 | + |
| 163 | + |
| 164 | +### onActiveStateChange |
| 165 | + |
| 166 | +```ts |
| 167 | +onActiveStateChange?: (active: boolean) => void; |
| 168 | +``` |
| 169 | + |
| 170 | +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. |
| 171 | + |
| 172 | +### delayLongPress |
| 173 | + |
| 174 | +```ts |
| 175 | +delayLongPress?: number; |
| 176 | +``` |
| 177 | + |
| 178 | +Defines the delay, in milliseconds, after which the [`onLongPress`](#onlongpress) callback gets called. By default set to `600`. |
| 179 | + |
| 180 | +### underlayColor |
| 181 | + |
| 182 | +```ts |
| 183 | +underlayColor?: string; |
| 184 | +``` |
| 185 | + |
| 186 | +Background color of underlay. |
| 187 | + |
| 188 | +### underlayActiveOpacity |
| 189 | + |
| 190 | +```ts |
| 191 | +underlayActiveOpacity?: number; |
| 192 | +``` |
| 193 | + |
| 194 | +Defines the opacity of underlay when the button is active. |
| 195 | + |
| 196 | +### activeOpacity |
| 197 | + |
| 198 | +```ts |
| 199 | +activeOpacity?: number; |
| 200 | +``` |
| 201 | + |
| 202 | +Defines the opacity of the whole component when the button is active. |
| 203 | + |
| 204 | +### underlayInitialOpacity |
| 205 | + |
| 206 | +```ts |
| 207 | +underlayInitialOpacity?: number; |
| 208 | +``` |
| 209 | + |
| 210 | +Defines the initial opacity of underlay when the button is inactive. By default set to `0`. |
| 211 | + |
| 212 | +### initialOpacity |
| 213 | + |
| 214 | +```ts |
| 215 | +initialOpacity?: number; |
| 216 | +``` |
| 217 | + |
| 218 | +Defines the initial opacity of the whole component when the button is inactive. By default set to `1` |
| 219 | + |
| 220 | +<HeaderWithBadges platforms={['android']}> |
| 221 | +### androidRipple |
| 222 | +</HeaderWithBadges> |
| 223 | + |
| 224 | +<CollapsibleCode |
| 225 | +label="Show composed types definitions" |
| 226 | +expandedLabel="Hide composed types definitions" |
| 227 | +lineBounds={[0, 1]} |
| 228 | +src={` |
| 229 | +androidRipple?: PressableAndroidRippleConfig; |
| 230 | +
|
| 231 | +type PressableAndroidRippleConfig = { |
| 232 | + color?: (string | OpaqueColorValue); |
| 233 | + borderless?: boolean; |
| 234 | + radius?: number; |
| 235 | + foreground?: boolean; |
| 236 | +} |
| 237 | +`}/> |
| 238 | + |
| 239 | +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. |
0 commit comments