Git Product home page Git Product logo

react-native-tip's Introduction

react-native-tip

React Native Tip is a simple package inspired in MaterialUI-Tooltip that helps you to show a quick tip to the user and highlight some important item in your app. It is useful to explain the user some funcionality.



Demo of react-native-tip

npm version npm downloads npm licence



Installation

To install the latest version of react-native-tip you only need to run:

npm install --save react-native-tip

or

yarn add react-native-tip



Try it out

You can find the examples above on src/example.



Basic Usage

Import TipProvider and place it at the very bottom of your App.js as below:

import React from "react";
import { SafeAreaView } from "react-native";
import TipProvider from "react-native-tip";

export default class App extends React.Component {
    render() {
        return (
            <SafeAreaView style={{ flex: 1 }}>
                ... all your stuff

                <TipProvider
                    ...global options, see below
                />
            </SafeAreaView>
        );
    }
}



Show a tip

To show a tip you need to import the Tip component and wrap the component you want to highlight inside it as shown below:

import React from "react";
import { Text } from "react-native";
import { Tip } from "react-native-tip";

class App extends React.Component {
  render() {
    return (
        <Tip
            title="Title"
            body="body"
        >
            <Text
                style={{
                    padding: 10,
                    fontWeight: 'bold',
                    fontSize: 20
                }}
            >
                Show tip
            </Text>
        </Tip>
    );
  }
}

When you wrap a component inside <Tip> it becomes a touchable.
When you press it, it shows the tip automatically by default but you can change that by setting the props active = false.

OBS: if the item is already a pressable component, you have to show or close the tip manually by importing showTip(), closeTip() help functions.

import React from 'react'
import { View, StyleSheet, TouchableOpacity, Button } from 'react-native'
import { showTip, closeTip, Tip } from './Tip'
import Icon from 'react-native-vector-icons/Ionicons'

const Screen = ({ navigation }) => {
    const [_showTip, setShowTip] = React.useState(true)

    return (
        <View style={styles.container}>
            <Tip
                id='heart'
                title="Do you liked it?"
                body="Remember to hit the heart if you enjoyed the content"
                showItemPulseAnimation
                pulseColor='#ff8080'
                active={false}
            >
                <TouchableOpacity
                    onPress={() => {
                        _showTip && showTip('heart')
                        setShowTip(false)
                    }}
                    style={{ padding: 10, borderRadius: 50 }}
                >
                    <Icon name='heart' color='red' size={35}/>
                </TouchableOpacity>
            </Tip>

            <View style={{ width: 200 }}>
                <Button
                    title="Show heart tip"
                    onPress={() => showTip('heart')}
                />
            </View>
        </View>
    )
}



Show a tip tour

You can create a tour with the tips you choose by setting a list of steps and pass it as a param of showTipTour(steps) helper function.
Each step receives a series of params specified in TipStep Props below.
You can find a complete example in src/example/components/TourButton



Tip Props

Property Type Description
id string or number The tip's id, useful to control it.
title string The title text of your tip.
titleStyle TextStyle Style for the title of your tip.
body string The body text of your tip.
bodyStyle TextStyle Style for the body of your tip.
style ViewStyle Style of the item wrapper component: <Tip style={style}>.
activeItemStyle ViewStyle Style for the item when the tip is open.>`.
tipContainerStyle ViewStyle Style for the tip. Use carefully, this can mess up the tip's position.
overlayOpacity number Set opacity intensity of overlay. default 0.6.
renderTip ({ titleStyle:TextStyle, bodyStyle:TextStyle }) => React.Component; Set a custom component to be rendered inside your tip. You can inject your current tip's global titleStyle and bodyStyle (if you defined one in your TipProvider) props direct in your custom tip component with titleStyle and bodyStyle params.
showItemPulseAnimation boolean Show item pulse animation when tip is open.
pulseColor string Set pulse animation color.
pulseStyle ViewStyle Style for the pulse animation.
pulseIntensity number Style for the pulse animation intensity size.
dismissable boolean Allow auto dismiss on touch overlay.
active boolean Default = true If true the item becomes pressable and shows the tip automatically when pressed. OBS: if the item is already a pressable component, you should show or close it manually by using showTip(), closeTip() help functions.
onPressItem () => void Trigger your custom action on item press.
onTipPress () => void Trigger your custom action on tip press.
onDismiss () => void Override dismiss natural action.



TipProvider Props

You can set a default style for all your tips with the following:

Property Type Description
tipContainerStyle ViewStyle Set global style for the tip wrapper.
titleStyle TextStyle Set global style for the title of your tip.
bodyStyle TextStyle Set global style for the body of your tip.
overlayOpacity number Set global opacity intensity of overlay. default 0.6.
showItemPulseAnimation boolean Set global pulse animation on item when tip is open.
pulseColor string Set global pulse animation color.
pulseStyle ViewStyle Set global style for the pulse animation.
pulseIntensity number Set global pulse animation intensity size.
darkMode boolean When true set a dark custom color scheme for your tip. It can be overwritten by titleStyle and bodyStyle props.
prevButtonLabel string Label for Prev action button on tip tour mode.
nextButtonLabel string Label for Next action button on tip tour mode.
closeButtonLabel string Label for Close action button on tip tour mode.
prevNextButtonStyle ViewStyle Style for Next, Prev, Close action buttons on tip tour mode.
prevNextTextStyle TextStyle Style for Next, Prev, Close action buttons text on tip tour mode.



Helper functions

Property Type Description
showTip (tipId?: string, delay?: number, props?: Partial<ITip>) => void Show your tip, can be called anywhere in your code. * You can show a specific tip by passing its id. * You can delay your tip's appearing by passing a delay number in milliseconds, useful to await async tasks live navigate to another screen, default=0
closeTip ()=>void Close the current opened tip, can be called anywhere in your code.
showTipTour (steps: ITipStep[])=>void Set a tip tour sequence.


TipStep Props

Property Type Description
id string Current tip id, required
prevId string Previous tip id, optional
nextId string Next tip id, optional
delay number Timeout before triggering the tip change to next or previous one.
prevAction () => void Action to be executed right before Prev button is pressed. Use it with delay prop for async tasks.
nextAction () => void Action to be executed right before Next button is pressed. Use it with delay prop for async tasks.



License

MIT

react-native-tip's People

Contributors

maicongilton avatar noway avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

react-native-tip's Issues

Can we make it so that it doesn't close the keyboard if the keyboard is open

Currently, I added tip view below textinput and I am showing tip if user enters more than 30 letters, The issue is it drops the keyboard, An as soon as it does tip trigger component appears twice (most probably because of the keyboard was dropping at the same time).
Fixes that can work: Make the tip play nicely with keyboard, Tip can be opened/closed even when the keyboard is visible.
If it is gonna drop the keyboard then it should show the tip after that animation/transition is finished. Might be interactionManager can work here.

The tip image is duplicated only on Android devices

This is only happening on android devices when i click on the button that is wrapped in . It showing the duplicated button right below the wrapped button

This is the code:

<Tip
 id={tooltipId}
 body={FAVORITE.PRICE_MAY_CHANGE}
 bodyStyle={styles.tooltipCaption}
 active={false}
 onDismiss={() => this.dismissPriceTooltip(tooltipId)}
 tipContainerStyle={styles.tooltipStyle}
 overlayOpacity={-1}
>
 <TouchableOpacity onPress={() => this.showHidePriceTooltip(tooltipId)}>
  <Image
   source={toolTipIcon}
   style={styles.tooltipIcon}
  />
 </TouchableOpacity>
</Tip>

And this is the duplicated button on android:

Screenshot 2022-12-23 at 11 08 22

I think It's happening because of the {this.renderItem()} on tipProvider.js

Could you check on this? Thanks!

Crash with react navigation

Thanks for your lib!
I have a crash when I use it with react-navigation (v5). If I use Tip on a screen in a Stack Navigator for example. Here the following step:

  1. Go to the screen with Tip
  2. Press on Tip => it's working as expected
  3. Go back in navigation stack
  4. Return to the screen with Tip
  5. Press on Tip, this error appear:
Invariant Violation: [1083,"RCTView",71,{"accessible":true,"position":"absolute","top":"<<NaN>>","left":"<<NaN>>","transform":[{"translateX":"<<NaN>>"},{"translateY":"<<NaN>>"}],"opacity":1,"focusable":true}] is not usable as a native method argument

This error is located at:
    in RCTView (at View.js:34)
    in View (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at TouchableOpacity.js:224)
    in TouchableOpacity (at TouchableOpacity.js:302)
    in ForwardRef (at TipProvider.js:394)
    in TipProvider (at App.tsx:139)
    in App (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)

Crash on android and ios.

Invariant Violation: [2963,"RCTView",11,{"position":"absolute","width":102,"height":44,"top":"<<NaN>>","left":75,"transform":[{"translateX":-51},{"translateY":-22}],"justifyContent":"center","alignItems":"center"}] is not usable as a native method argument

Experiencing this error:

Invariant Violation: [2963,"RCTView",11,{"position":"absolute","width":102,"height":44,"top":"<<NaN>>","left":75,"transform":[{"translateX":-51},{"translateY":-22}],"justifyContent":"center","alignItems":"center"}] is not usable as a native method argument

This error is located at:
    in RCTView (at TipProvider.js:416)
    in RCTView (at AppContainer.js:101)
    in RCTView (at AppContainer.js:119)
    in AppContainer (at Modal.js:250)
    in RCTView (at Modal.js:271)
    in RCTModalHostView (at Modal.js:258)
    in Modal (at TipProvider.js:439)
    in TipProvider (created by App)
    in RCTSafeAreaView (at SafeAreaView.js:55)
    in SafeAreaView (created by App)
    in App (at renderApplication.js:40)
    in RCTView (at AppContainer.js:101)
    in RCTView (at AppContainer.js:119)
    in AppContainer (at renderApplication.js:39)

fn
    NativeModules.js:137:10
Component.prototype.setState
    react.development.js:325:31
showTip
    TipProvider.js:41:8
tryCatch
    runtime.js:63:44
invoke
    runtime.js:293:30
tryCatch
    runtime.js:63:44
invoke
    runtime.js:154:28
PromiseImpl.resolve.then$argument_0
    runtime.js:164:19
tryCallOne
    core.js:37:14
setImmediate$argument_0
    core.js:123:25

react-native info:

yarn run react-native info                                                                                                                                                                                                  *[ch8764/native-new-design]
yarn run v1.22.10
$ /Users/ilia/myapp/myapp/node_modules/.bin/react-native info
warn Your project is using deprecated "rnpm" config that will stop working from next release. Please use a "react-native.config.js" file to configure the React Native CLI. Migration guide: https://github.com/react-native-community/cli/blob/master/docs/configuration.md
warn The following packages use deprecated "rnpm" config that will stop working from next release:
  - react-native-comparison-slider: https://npmjs.com/package/react-native-comparison-slider
  - react-native-orientation: https://github.com/yamill/react-native-orientation#readme
  - react-native-video: https://npmjs.com/package/react-native-video
  - react-native-zip-archive: https://github.com/mockingbot/react-native-zip-archive
Please notify their maintainers about it. You can find more details at https://github.com/react-native-community/cli/blob/master/docs/configuration.md#migration-guide.
info Fetching system and libraries information...
System:
    OS: macOS 11.3.1
    CPU: (8) arm64 Apple M1
    Memory: 269.39 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.5.0 - /var/folders/85/2xpmzxms1tsgzr9nqnhszzfw0000gn/T/yarn--1628129877401-0.3539187398275403/node
    Yarn: 1.22.10 - /var/folders/85/2xpmzxms1tsgzr9nqnhszzfw0000gn/T/yarn--1628129877401-0.3539187398275403/yarn
    npm: 7.19.1 - /opt/homebrew/bin/npm
    Watchman: 2021.06.07.00 - /opt/homebrew/bin/watchman
  SDKs:
    iOS SDK:
      Platforms: iOS 14.5, DriverKit 20.4, macOS 11.3, tvOS 14.5, watchOS 7.4
    Android SDK:
      API Levels: 23, 25, 27, 28, 29, 30
      Build Tools: 28.0.3, 29.0.2, 29.0.3, 30.0.2, 30.0.3
      System Images: android-29 | Intel x86 Atom_64, android-29 | Google APIs Intel x86 Atom, android-30 | Google APIs Intel x86 Atom
  IDEs:
    Android Studio: 4.1 AI-201.8743.12.41.7199119
    Xcode: 12.5.1/12E507 - /usr/bin/xcodebuild
  npmPackages:
    react: 16.9.0 => 16.9.0
    react-native: 0.61.5 => 0.61.5
✨  Done in 10.97s.

setup:
App.tsx:

	render(): JSX.Element {
		return (
			<SafeAreaView style={{flex:1}}>
				<Provider store={store}>
					<Main />
				</Provider>
				<TipProvider 
				/>
			</SafeAreaView>
		)
	}

component:

	render() {
		return (
			<>
			<Tip
				id="heart"
				title="Title"
				body="body"
			>
				<Text
					style={{
						padding: 10,
						fontWeight: 'bold',
						fontSize: 20
					}}
				>
					Show tip
				</Text>
			</Tip>
...

						<Button
							title="Show heart tip"
							onPress={() => showTip('heart')}
						/>

...
</>
)
}

Make "nextAction/prevAction" execute before searching for tip in "showTipTour()"

I want to do a tour where it navigates between pages in a stack but I cant because the next page hasn't been mounted yet so it can't find the tip id, and if it can't find the tip id it just doesn't execute the nextAction method. it should be the action method is executed first, so that it i can navigate to the next page. and by that point it is not mounted, and so it can detect the tip id now. i feel like that makes sense. also in the docs it says that the actions are "executed right before Next/Prev button is pressed." I don't understand this, it gets executed AFTER you press the button? that's what triggers it right?
Anyway this makes it so i can only do a tour for the page I'm currently in and can't navigate through the app.

Tips are not found in different screen from currentTip during TipTour

Thank you for sharing this library. Very insightful.

I think there is a limitation in TipTour implementation. It fails to find nextTips when they are present in a different screen which is not loaded (Tip is not registered) until we navigate to that screen.

I think we should call nextAction/prevAction before finding the tip by id in the registry. So that once nextAction is called,

  • we navigate to the screen,
  • the tip is registered
  • then we can find it after some predefined delay (depending time for navigation animation + set layout)

Typescript No overload matches this call.

Error:

No overload matches this call.
  Overload 1 of 2, '(props: ITipProvider | Readonly<ITipProvider>): TipProvider', gave the following error.
    Type '{ children: Element; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<TipProvider> & Readonly<ITipProvider>'.
  Overload 2 of 2, '(props: ITipProvider, context: any): TipProvider', gave the following error.
    Type '{ children: Element; }' has no properties in common with type 'IntrinsicAttributes & IntrinsicClassAttributes<TipProvider> & Readonly<ITipProvider>'.

My Code:

import React from "react";
import { PersistGate } from "redux-persist/integration/react";
import { Provider } from "react-redux";
import TipProvider from "react-native-tip";
import { store, persistor } from "./src/redux";

type Props = {
  children: JSX.Element;
};
const Providers = ({ children }: Props) => (
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}>
      <TipProvider>
        {children} 
      </TipProvider>
    </PersistGate>

  </Provider>
);

export default Providers;

Screenshot 2023-08-26 at 1 20 36 AM

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.