Skip to content

meanguppy/react-native-popover-reanimated

Repository files navigation

react-native-popover-reanimated

Popover view for React Native via react-native-reanimated

Installation

npm install react-native-popover-reanimated

Setup

import { PopoverManager } from 'react-native-popover-reanimated';

Wrap your application render with the PopoverManager component. Ensure react-native-gesture-handler has already been set up with the GestureHandlerRootView as well.

  return (
    <GestureHandlerRootView style={styles.flex}>
      <PopoverManager>
        {/* ... application ... */}
      </PopoverManager>
    </GestureHandlerRootView>
  );

Optional props

Additional props can be passed to the PopoverManager to customize the positioning behavior of the popover view. The default values can be seen here:

  <PopoverManager
    originAnchor="bottom"
    contentAnchor="top"
    offsetX={0}
    offsetY={0}
    padding={16}>
  • The anchors determine where the popover view will be presented
    • originAnchor refers to the view marked as the origin (originRef)
    • contentAnchor refers to the content rendered inside the popover view
    • The two views will line up on their respective anchors. With the default configuration above, the center-top of the content view will sit on the center-bottom of the origin view.
    • Possible values are: 'top-left' | 'top' | 'top-right' | 'left' | 'center' | 'right' | 'bottom-left' | 'bottom' | 'bottom-right'
  • offsetX/offsetY: amount in pixels to offset the content view on the respective axis
  • padding: amount in pixels that the content view will be clamped to/spaced from the edge of the screen

Usage

import { usePopoverView } from 'react-native-popover-reanimated';
  1. Define a render function that returns the contents you wish to place inside the popover view. To avoid unnecessary rerenders, this method should be defined with the useCallback hook.
  const renderContent = useCallback(() => (
    <View>
      <Text>Hello world</Text>
    </View>
  ), []);
  1. Call the usePopoverView hook, passing the render function as the first argument, in order to access the popover handlers.
  const { originRef, openPopover, closePopover } = usePopoverView(renderContent);
  1. Assign the originRef as the ref prop of a native view, such as a View. This component determines the visual origin at which the popover will appear when the openPopover method is invoked. The component must be backed by a native view in order to make use of the measure function. React Native will attempt to optimize the native view hierarchy by not rendering a View it deems unnecessary. Add the collapsable={false} prop to prevent this from happening.
  return (
    <View ref={originRef} collapsable={false}>
      <Button onPress={openPopover} title="Open popover" />
    </View>
  );
  1. Call the openPopover function from any source in order to present the popover view. Any touch down outside of the popover content bounds will instantly close the view.

The renderContent callback also provides a closePopover method as a parameter that can be used to trigger a close from within the popover content itself:

  const renderContent = useCallback((closePopover) => (
    <View>
      <Text>Hello world</Text>
      <Button title="Close" onPress={closePopover} />
    </View>
  ), []);

To override the configuration props set on the PopoverManager for a particular popover view, pass a partial configuration object as the second parameter of usePopoverView:

  const { originRef, openPopover } = usePopoverView(renderContent, {
    originAnchor: 'bottom-right',
    padding: 8,
  });

Example: dropdown menu component

export function Dropdown({ data, onSelect }) {

  const renderContent = useCallback((closePopover) => {
    const buttons = data.map((item) => (
      <Button
        title={item}
        onPress={() => {
          onSelect(item);
          closePopover();
        }}
      />
    ));
    return (
      <View style={styles.content}>{buttons}</View>
    );
  }, [data, onSelect]);

  const { originRef, openPopover } = usePopoverView(renderContent);

  return (
    <View style={styles.container}>
      <View ref={originRef} collapsable={false}>
        <Button onPress={openPopover} title="Select item" />
      </View>
    </View>
  );
}

export default function App() {
  return (
    <GestureHandlerRootView style={styles.flex}>
      <PopoverManager>
        <Dropdown
          data={['One', 'Two', 'Three']}
          onSelect={(item) => console.log('Selected', item)}
        />
      </PopoverManager>
    </GestureHandlerRootView>
  );
}

TODO

  • Popover styling, padding, animation configuration
  • Accessibility setup

Contributing

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

License

MIT

About

React Native Popover View built with react-native-reanimated

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published