• Stars
    star
    2,002
  • Rank 23,135 (Top 0.5 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created about 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Step-by-step walkthrough tooltip for your react native app

React Native Copilot

Step-by-step walkthrough for your react native app!

React Native Copilot

Demo

Installation

yarn add react-native-copilot

# or with npm:

npm install --save react-native-copilot

Optional: If you want to have the smooth SVG animation, you should install and link react-native-svg.

Usage

Wrap the portion of your app that you want to use copilot with inside <CopilotProvider>:

import { CopilotProvider } from "react-native-copilot";

const AppWithCopilot = () => {
  return (
    <CopilotProvider>
      <HomeScreen />
    </CopilotProvider>
  );
};

NOTE: The old way of using copilot with the copilot() HOC maker is deprecated in v3. It will continue to work but it's not recommended and may be removed in the future.

Before defining walkthrough steps for your react elements, you must make them walkthroughable. The easiest way to do that for built-in react native components, is using the walkthroughable HOC. Then you must wrap the element with CopilotStep.

import {
  CopilotProvider,
  CopilotStep,
  walkthroughable,
} from "react-native-copilot";

const CopilotText = walkthroughable(Text);

const HomeScreen = () => {
  return (
    <View>
      <CopilotStep text="This is a hello world example!" order={1} name="hello">
        <CopilotText>Hello world!</CopilotText>
      </CopilotStep>
    </View>
  );
};

Every CopilotStep must have these props:

  1. name: A unique name for the walkthrough step.
  2. order: A positive number indicating the order of the step in the entire walkthrough.
  3. text: The text shown as the description for the step.

Additionally, a step may set the active prop, a boolean that controls whether the step is used or skipped.

In order to start the tutorial, you can call the start function from the useCopilot hook:

const HomeScreen = () => {
  return (
    <View>
      <Button title="Start tutorial" onPress={() => start()} />
    </View>
  );
};

If you are looking for a working example, please check out this link.

Overlays and animation

The overlay in react-native-copilot is the component that draws the dark transparent over the screen. React-native-copilot comes with two overlay options: view and svg.

The view overlay uses 4 rectangles drawn around the target element using the <View /> component. We don't recommend using animation with this overlay since it's sluggish on some devices specially on Android.

The svg overlay uses an SVG path component for drawing the overlay. It offers a nice and smooth animation but it depends on react-native-svg. If you are using expo, you can install it using:

expo install react-native-svg

Or if you are using react-native-cli:

yarn add react-native-svg

# or with npm

npm install --save react-native-svg

cd ios && pod install

You can specify the overlay by passing the overlay prop to the <CopilotProvider /> component:

<CopilotProvider overlay="svg" {/* or "view" */}>
  <App />
</CopilotProvider>

By default, if overlay is not explicitly specified, the svg overlay will be used if react-native-svg is installed, otherwise the view overlay will be used.

Custom tooltip and step number UI components

You can customize the tooltip and the step number components by passing a component to the CopilotProvider component. If you are looking for an example tooltip component, take a look at the default ui implementations.

const TooltipComponent = ({
  isFirstStep,
  isLastStep,
  handleNext,
  handleNth,
  handlePrev,
  handleStop,
  currentStep,
}) => (
  // ...
);


<CopilotProvider tooltipComponent={TooltipComponent} stepNumberComponent={StepComponent}>
  <App />
</CopilotProvider>

Navigating through the tour

The above code snippet shows the functions passed to the tooltip. These are your primary navigation functions. Some notes on navigation:

  • handleNext and handlePrev will move the mask from the current wrapped component immediately to the next.

  • You can use handleStop in conjunction with handleNth to effectively "pause" a tour, allowing for user input, animations or any other interaction that shouldn't have the mask applied. Once you want to pick the tour back up, call handleNth on the next tour step.

Note that handleNth is 1-indexed, which is in line with what your step orders should look like.

Custom tooltip styling

You can customize tooltip's wrapper style:

const style = {
  backgroundColor: "#9FA8DA",
  borderRadius: 10,
  paddingTop: 5,
};

<CopilotProvider tooltipStyle={style}>
  <App />
</CopilotProvider>;

Manage tooltip width

By default, the tooltip width is calculated dynamically. You can make it fixed-size by overriding both width and maxWidth, check the example bellow:

const MARGIN = 8;
const WIDTH = Dimensions.get("window").width - 2 * MARGIN;

<CopioltProvider tooltipStyle={{ width: WIDTH, maxWidth: WIDTH, left: MARGIN }}>
  <App />
</CopilotProvider>;

Custom tooltip arrow color

You can customize the tooltip's arrow color:

<CopilotProvider arrowColor="#9FA8DA">
  <App />
</CopilotProvider>

Custom overlay color

You can customize the mask color - default is rgba(0, 0, 0, 0.4), by passing a color string to the CopilotProvider component.

<CopilotProvider backdropColor="rgba(50, 50, 100, 0.9)">
  <App />
</CopilotProvider>

Custom svg mask Path

You can customize the mask svg path by passing a function to the CopilotProvider component.

function SvgMaskPathFn(args: {
  size: Animated.valueXY;
  position: Animated.valueXY;
  canvasSize: {
    x: number;
    y: number;
  };
  step: Step;
}): string;

Example with circle:

const circleSvgPath = ({ position, canvasSize }) =>
  `M0,0H${canvasSize.x}V${canvasSize.y}H0V0ZM${position.x._value},${position.y._value}Za50 50 0 1 0 100 0 50 50 0 1 0-100 0`;

<CopilotProvider svgMaskPath={circleSvgPath}>
  <App />
</CopilotProvider>;

Example with different overlay for specific step:

Give name prop for the step

<CopilotStep text="This is a hello world example!" order={1} name="hello">
  <CopilotText>Hello world!</CopilotText>
</CopilotStep>

Now you can return different svg path depending on step name

const customSvgPath = (args) => {
  if (args.step?.name === "hello") {
    return `M0,0H${canvasSize.x}V${canvasSize.y}H0V0ZM${position.x._value},${position.y._value}Za50 50 0 1 0 100 0 50 50 0 1 0-100 0`;
  } else {
    return `M0,0H${canvasSize.x}V${canvasSize.y}H0V0ZM${position.x._value},${
      position.y._value
    }H${position.x._value + size.x._value}V${
      position.y._value + size.y._value
    }H${position.x._value}V${position.y._value}Z`;
  }
};

<CopilotProvider svgMaskPath={customSvgPath}>
  <App />
</CopilotProvider>;

Custom components as steps

The components wrapped inside CopilotStep, will receive a copilot prop with a mutable ref and onLayou which the outermost rendered element of the component or the element that you want the tooltip be shown around, must extend.

import { CopilotStep } from "react-native-copilot";

const CustomComponent = ({ copilot }) => (
  <View {...copilot}>
    <Text>Hello world!</Text>
  </View>
);

const HomeScreen = () => {
  return (
    <View>
      <CopilotStep text="This is a hello world example!" order={1} name="hello">
        <CustomComponent />
      </CopilotStep>
    </View>
  );
};

Custom labels (for i18n)

You can localize labels:

<CopilotProvider
  labels={{
    previous: "Vorheriger",
    next: "Nächster",
    skip: "Überspringen",
    finish: "Beenden"
  }}
>

Adjust vertical position

In order to adjust vertical position pass verticalOffset to the CopilotProvider component.

<CopilotProvider verticalOffset={36}>

Triggering the tutorial

Use const {start} = useCopilot() to trigger the tutorial. You can either invoke it with a touch event or in useEffect to start after the comopnent mounts. Note that the component and all its descendants must be mounted before starting the tutorial since the CopilotSteps need to be registered first.

Usage inside a ScrollView

Pass the ScrollView reference as the second argument to the start() function. eg start(undefined, scrollViewRef)

import { ScrollView } from "react-native";

class HomeScreen {
  componentDidMount() {
    // Starting the tutorial and passing the scrollview reference.
    this.props.start(false, this.scrollView);
  }

  componentWillUnmount() {
    // Don't forget to disable event handlers to prevent errors
    this.props.copilotEvents.off("stop");
  }

  render() {
    <ScrollView ref={(ref) => (this.scrollView = ref)}>// ...</ScrollView>;
  }
}

Listening to the events

useCopilot provides a copilotEvents function prop to allow you to track the progress of the tutorial. It utilizes mitt under the hood.

List of available events is:

  • start — Copilot tutorial has started.
  • stop — Copilot tutorial has ended or skipped.
  • stepChange — Next step is triggered. Passes Step instance as event handler argument.

Example:

import { useCopilot } from "react-native-copilot";

const HomeScreen = () => {
  const { copilotEvents } = useCopilot();

  useEffect(() => {
    const listener = () => {
      // Copilot tutorial finished!
    };

    copilotEvents.on("stop", listener);

    return () => {
      copilotEvents.off("stop", listener)
    };
  }, []);

  return (
    // ...
  );
}

Contributing

Issues and Pull Requests are always welcome.

If you are interested in becoming a maintainer, get in touch with us by sending an email or opening an issue. You should already have code merged into the project. Active contributors are encouraged to get in touch.

Creation of this project was sponsored by OK GROW!

More Repositories

1

made-in-iran

A list of cool projects made in Iran
TypeScript
833
star
2

vidact

A compiler that converts React-compatible codes to VanillaJS with no Virtual DOM
TypeScript
764
star
3

konsul

A react renderer for browser's dev console
JavaScript
615
star
4

grafgiti

Vandalize your github contributions wall.
JavaScript
412
star
5

react-native-loader

A collection of animated spinners for React Native
JavaScript
393
star
6

racket

A complete starting app for developing universal React/Redux web apps with generators, best practices and more
JavaScript
290
star
7

react-native-easy-dnd

Drag and drop with react-native made simple
TypeScript
125
star
8

angular-persian

🌏 Persian tools for angular.js
CoffeeScript
98
star
9

lithree.js

🔮 Lightweight 3D WebGL framework written in ES6
JavaScript
42
star
10

react-native-ximage

An alternative to react native's Image component with cache support.
JavaScript
31
star
11

react-use-context-selector

Context selector hook for React
TypeScript
29
star
12

openbabel-node

OpenBabel Bindings for Node.js
C++
26
star
13

php-jalali-extension

A php extension for Jalali dates
Shell
20
star
14

DateTimeBundle

A Symfony2 Bundle to format DateTime to string according to a Calendar and a Datepicker FormType.
JavaScript
16
star
15

telegram-vanilla-client

TypeScript
15
star
16

react-markdown-native

Render Markdown as React native components
JavaScript
14
star
17

volley

A Web-Based Volleyball game
JavaScript
12
star
18

mol3d

A chemical visualization tool on top of WebGL
JavaScript
10
star
19

Razi

A new scientific chemistry library for java.
Java
10
star
20

pasoor

♠️ A simple API for game cards.
JavaScript
9
star
21

molcanvas.js

A WebGL molecule renderer and editor
JavaScript
7
star
22

goron

Yet another graphical database management tool [WIP]
JavaScript
7
star
23

muzik

A simple music player made with react. I made it for an "interview" test but never joined the company.
JavaScript
7
star
24

vscode-shopify-i18n

TypeScript
6
star
25

shelem

♥️ Shelem (a perisan card game) made with react native
JavaScript
6
star
26

mohebifar.ir

Mohamad Mohebifar's blog
HTML
4
star
27

openmm-transformer

A cleaner way to manage custom forces in OpenMM
Python
4
star
28

muniranians

JavaScript
4
star
29

GayPI

:octocat: Isomorphic JavaScript API wrapper around the Github API v3.
JavaScript
4
star
30

truck-cli

JavaScript
3
star
31

openmm-buckingham-plugin

C++
3
star
32

chem.js

A molecular modeling JavaScript framework.
JavaScript
3
star
33

CalendarBundle

A Symfony2 Bundle to show times with any type of calendar (Persian هجری, Gregorian, ...)
PHP
2
star
34

fix-pdb

A simple script for fixing broken PDB files
Python
2
star
35

pybel-orca

Python code around pybel to write inputs and read outputs of the ab initio package, ORCA
Python
2
star
36

cssTransit

Javascript CSS Transition
JavaScript
1
star
37

react-konsole

1
star
38

node-parsi-payment

A Node.js module providing access to the Iran's Shetab Payment API
JavaScript
1
star
39

smirnoff

The SMIRks Native Open Force Field (SMIRNOFF)
Jupyter Notebook
1
star
40

janshop

Simple RESTful django content management framework
HTML
1
star