Skip to content

Trancever/reanimated-collapsible-helpers

Repository files navigation

reanimated-collapsible-helpers

Build Status Version MIT License

A cross-platform smooth expand/collapse animation helpers for React Native.

Features

  • Smooth animations
  • Headless UI
  • Cross-platform (iOS, Android, Web)
  • Highly customizable
  • Fully typed with TypeScript

Demo

demo.mov

Installation

Open a Terminal in the project root and run:

npm install reanimated-collapsible-helpers

or

yarn add reanimated-collapsible-helpers

Now we need to install react-native-reanimated.

If you are using Expo, to ensure that you get the compatible versions of the libraries, run:

expo install react-native-reanimated

If you are not using Expo, run the following:

npm install react-native-reanimated

or

yarn add react-native-reanimated

If you are using Expo, you are done. Otherwise, continue to the next steps.

Next, we need to link these libraries. The steps depends on your React Native version:

  • React Native 0.60 and higher

    On newer versions of React Native, linking is automatic.

    To complete the linking on iOS, make sure you have Cocoapods installed. Then run:

    cd ios
    pod install
    cd ..
  • React Native 0.59 and lower

    If you're on an older React Native version, you need to manually link the dependencies. To do that, run:

    react-native link react-native-reanimated

We're done! Now you can build and run the app on your device/simulator.

Usage

import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import {
  useCollapsible,
  AnimatedSection,
} from 'reanimated-collapsible-helpers';

export default function App() {
  const { animatedHeight, height, onPress, onLayout, state } = useCollapsible();

  return (
    <View style={styles.background}>
      <View style={styles.overflow}>
        <TouchableOpacity onPress={onPress} style={styles.button}>
          <Text style={styles.buttonText}>
            {state === 'expanded' ? 'Collapse' : 'Expand'}
          </Text>
        </TouchableOpacity>
        <AnimatedSection
          animatedHeight={animatedHeight}
          onLayout={onLayout}
          state={state}
        >
          <View style={styles.textContainer}>
            <Text>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean
              quis erat suscipit, mollis nibh ut, venenatis lectus. Orci varius
              natoque penatibus et magnis dis parturient montes, nascetur
              ridiculus mus.
            </Text>
          </View>
        </AnimatedSection>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  background: {
    flex: 1,
    backgroundColor: '#efefef',
    padding: 20,
  },
  overflow: {
    overflow: 'hidden',
    backgroundColor: 'white',
    borderRadius: 6,
  },
  button: {
    padding: 10,
    textAlign: 'center',
  },
  buttonText: {
    fontSize: 20,
  },
  textContainer: {
    padding: 15,
  },
});

Try this example on Snack

API reference

The package exports one hook and one component:

  • useCollapsible hook
  • AnimatedSection component

useCollapsible

A hook responsible for managing state, animation and providing helper functions.

Usage looks like this:

const { animatedHeight, height, onPress, onLayout, state } = useCollapsible();

It accepts one argument config - an object containing following properties:

  • duration: A number representing an expand/collapse animation duration (Optional, defaults to 250ms).
  • easing: An easing function used by the animation (Optional, defaults to Easing.out(Easing.ease)).

Hook returns an object with following properties:

  • state: An enum representing a state of the animation - expanded or collapsed.
  • height: A number representing full height of the collapsible section. Handy for defining upper bounds of the custom interpolations.
  • animatedHeight: An Animated.Value driving collapse/expand animations. It must be passed to the AnimatedSection component as a prop.
  • onLayout: A function that measures a collapsible element. It must be passed to the AnimatedSection component as a prop.
  • onPress: A function that toggles animation state when it's called. Pass it to a Touchable component, that on press, is supposed to expand/collapse some content.

AnimatedSection

A component that takes care of height measuring and animating.

Basic usage:

<AnimatedSection
  animatedHeight={animatedHeight}
  onLayout={onLayout}
  state={state}
>
  <Text>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean quis erat
    suscipit, mollis nibh ut, venenatis lectus.
  </Text>
</AnimatedSection>

Props

  • children: (Required) Accepts a React element that will be rendered as AnimatedSection content.
  • animatedHeight: (Required) An Animated.Value driving collapse/expand animations. Pass animatedHeight property returned by useCollapsible hook.
  • onLayout: (Required) A function that measures a collapsible element. Pass onLayout function returned by useCollapsible hook.
  • state: (Required) A state of the animation. It's used internally by the component to properly handle pointer events of the collapsed element. Pass state property returned by useCollapsible hook.
  • style: (Optional) A custom style property that will be passed to the underlying Animated.View - animated styles are supported.

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

Credits

Icons made by ultimatearm from www.flaticon.com