Skip to content

[Docs] Clickable#4022

Open
m-bert wants to merge 64 commits intomainfrom
@mbert/clickable-docs
Open

[Docs] Clickable#4022
m-bert wants to merge 64 commits intomainfrom
@mbert/clickable-docs

Conversation

@m-bert
Copy link
Copy Markdown
Contributor

@m-bert m-bert commented Mar 12, 2026

Description

This PR adds docs for Clickable component

Test plan

Read docs 🤓

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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)?

m-bert added a commit that referenced this pull request Apr 1, 2026
## 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>
Base automatically changed from @mbert/clickable to main April 1, 2026 15:11
@m-bert m-bert requested a review from j-piasecki April 3, 2026 10:19
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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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}`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
`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).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
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).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
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).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
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`.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Documentation Documentation change/enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants