pressto

repository·main·Indexed 21 days ago

https://github.com/enzomanuelmangano/pressto

A React Native library providing high-performance, animated pressables to replace TouchableOpacity. It leverages react-native-reanimated and react-native-gesture-handler to run animations on the main thread at 60fps. Features include pre-built components like PressableScale and PressableOpacity, a createAnimatedPressable API for custom animations, and a PressablesConfig provider for global settings. Includes eslint-plugin-pressto to enforce the 'worklet' directive in animation functions.

Tokens
9.4K
Snippets
36
Records
47
Agent score
74%

What's inside pressto

  1. Set global default props and handlers

    main

    Use PressablesConfig to apply default props (like rippleColor) or global event handlers (like haptics) to all pressables within the provider.

    • defaultProps: Applies standard React Native props to all children.
    • globalHandlers: Allows you to intercept onPress, onPressIn, or onPressOut events globally. Handlers receive the component's metadata.
    • skipGlobalHandlers: Use this prop on an individual pressable to opt out of global handlers while still firing its own local handlers.
    import { PressablesConfig } from 'pressto';
    import * as Haptics from 'expo-haptics';
    
    function App() {
      return (
        <PressablesConfig
          defaultProps={{ rippleColor: 'transparent' }}
          globalHandlers={{
            onPress: () => {
              Haptics.selectionAsync();
            },
          }}
        >
          <PressableScale onPress={() => {}} />
          {/* Opt out of haptics for this specific button */}
          <PressableScale skipGlobalHandlers onPress={() => {}} />
        </PressablesConfig>
      );
    }
  2. Access interaction states in custom pressables

    main

    When using createAnimatedPressable, you can access the following properties via the options argument to create complex interaction logic:

    • isPressed: true while the component is actively being pressed.
    • isToggled: true if the component is in a persistent toggle state.
    • isSelected: true if the component is the last pressed item in a group.
    • metadata: The component's specific metadata (or the global metadata from PressablesConfig).
    const ToggleButton = createAnimatedPressable((progress, options) => {
      'worklet';
      const { isPressed, isToggled, isSelected } = options;
    
      return {
        backgroundColor: isToggled ? '#4CAF50' : '#2196F3',
        opacity: isPressed ? 0.8 : 1,
        borderWidth: isSelected ? 3 : 0,
      };
    });
  3. Quickstart with PressableScale

    main

    Use the pre-built PressableScale component to add smooth, main-thread scaling animations to your components when they are pressed.

    import { PressableScale } from 'pressto';
    
    function App() {
      return (
        <PressableScale onPress={() => console.log('pressed')}>
          <Text>Press me</Text>
        </PressableScale>
      );
    }
  4. Configure eslint-plugin-pressto with ESLint Flat Config

    main

    To use the plugin with the modern ESLint Flat Config (eslint.config.js), import the plugin and add it to the plugins object, then enable the pressto/require-worklet-directive rule.

    const presstoPlugin = require('eslint-plugin-pressto');
    
    module.exports = [
      {
        plugins: {
          pressto: presstoPlugin,
        },
        rules: {
          'pressto/require-worklet-directive': 'error',
        },
      },
    ];
  5. Enable Web Hover support

    main

    To activate animations when a user hovers over a component on the web, use the activateOnHover prop. This can be applied to individual pressables or globally via PressablesConfig.

    // Per component
    <PressableScale activateOnHover onPress={() => {}} />
    
    // Or globally
    <PressablesConfig activateOnHover>
      <App />
    </PressablesConfig>
  6. Use metadata for type-safe design systems

    main

    You can pass a design system (like a theme object) into PressablesConfig via the metadata prop. This metadata is then available inside your createAnimatedPressable worklets, allowing for type-safe access to theme values.

    const theme = {
      colors: { primary: '#6366F1' },
      spacing: { medium: 16 },
    };
    
    type Theme = typeof theme;
    
    const ThemedButton = createAnimatedPressable<Theme>((progress, { metadata }) => {
      'worklet';
      return {
        backgroundColor: metadata.colors.primary,
        padding: metadata.spacing.medium,
      };
    });
    
    <PressablesConfig metadata={theme}>
      <ThemedButton onPress={() => {}} />
    </PressablesConfig>
  7. Install Pressto

    main

    Install pressto along with its required peer dependencies react-native-reanimated, react-native-gesture-handler, and react-native-worklets using your preferred package manager.

    bun add pressto react-native-reanimated react-native-gesture-handler react-native-worklets
  8. Configure global animation settings with PressablesConfig

    main

    Wrap your application (or a component tree) with PressablesConfig to set global animation behaviors, including animation types, configurations, and default visual values.

    import { PressablesConfig, PressableScale } from 'pressto';
    
    function App() {
      return (
        <PressablesConfig
          animationType="spring"
          animationConfig={{ damping: 30, stiffness: 200 }}
          config={{ minScale: 0.9, activeOpacity: 0.6 }}
        >
          <PressableScale onPress={() => console.log('pressed')}>
            <Text>Now with spring animation!</Text>
          </PressableScale>
        </PressablesConfig>
      );
    }