create "TouchableOpacity" for ReactJS without using react-native-web
You can achieve this affect with css transitions and using state to track when the user is clicking the button:
class App extends React.Component { state = { touched: false } toggleTouched = () => { this.setState( prevState => ({ touched: !prevState.touched })); } handleMouseUp = () => { // Handle smooth animation when clicking without holding setTimeout( () => { this.setState({ touched: false }); }, 150); } render () { const { touched } = this.state; const className = touched ? 'btn touched' : 'btn'; return ( <button className={className} onMouseDown={this.toggleTouched} onMouseUp={this.handleMouseUp} > Touch Here </button> ) }}ReactDOM.render(<App/>, document.getElementById('root'));
.btn { background: #ededed; padding: 10px 15px; border: none; outline: none; cursor: pointer; font-size: 15px; opacity: 1; transition: opacity 300ms ease;}.touched { opacity: 0.5;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script><div id="root"></div>
The answer from @ChaseDeAnda is really great. I have made my typescript component version of it
TouchableOpacity.tsx
import React from 'react'import classNames from 'classnames'import styles from './index.module.scss'export default function TouchableOpacity({ className, children, ...rest }: TTouchableOpacityProps) { const [touched, touchedSet] = React.useState(false) return ( <button className={classNames(styles.container, className)} style={{ opacity: touched ? 0.5 : 1, transition: 'opacity 300ms ease' }} onMouseDown={() => touchedSet(true)} onMouseUp={() => touchedSet(false)} {...rest}> {children} </button> )}
types.d.ts
type TTouchableOpacityProps = React.ButtonHTMLAttributes<HTMLButtonElement>
(you don't have to use the 'classnames` package - string interpolation is just fine)