npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@reactour/tour

v3.7.0

Published

<p align="center"> <a href="reactour.js.org"> <img alt="Reactour" title="Reactour" src="https://raw.githubusercontent.com/elrumordelaluz/reactour/main/logo.svg" width="250"></a> </p> <p align="center" style="margin-top: 40px;margin-bottom: 40px;"> <st

Downloads

247,105

Readme

Documentation

https://docs.react.tours

This documentation is for the latest release, which uses npm scoped package @reactour. The original reactour is now on branch v1 and its documentation can be found here.

Install

npm i -S @reactour/tour
# or
yarn add @reactour/tour

Usage

Add the TourProvider at the root of your Application, passing the steps of the elements to highlight during the Tour.

// ...
import { TourProvider } from '@reactour/tour'

ReactDOM.render(
  <TourProvider steps={steps}>
    <App />
  </TourProvider>,
  document.getElementById('root')
)

const steps = [
  {
    selector: '.first-step',
    content: 'This is my first Step',
  },
  // ...
]

Then somewhere down the Application tree, control the Tour using useTour hook.

import { useTour } from '@reactour/tour'

function App() {
  const { setIsOpen } = useTour()
  return (
    <>
      <p className="first-step">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent at
        finibus nulla, quis varius justo. Vestibulum lorem lorem, viverra porta
        metus nec, porta luctus orci
      </p>
      <button onClick={() => setIsOpen(true)}>Open Tour</button>
    </>
  )
}

Examples

Playground

The Playground is the perfect place to play aroud with all @reactour Components. Here is an online version.

Sandboxes

Edit @reactour/tour Demo Template

Feel free to make a PR proposing new sandboxes or demos to add in the playground.

TourProvider

steps?: StepType[]

Array of elements to highlight with special info and props.

selector: string | Element

A string containing one CSS Selector to match and highlight the element at the time of this step.

content: string | ({ setCurrentStep, transition, isHighlightingObserved, currentStep, setIsOpen }) => void

The content to show inside the Popover at the time of this step. Using a function have parameters to use inside content.

position?: 'top' | 'right' | 'bottom' | 'left' | 'center' | [number, number]

The preferred postion to position the Popover in relation with the highlighted element. Will be automatically calculated in case of unavailable space.

highlightedSelectors?: string[]

Array of CSS Selector to be included (by union) in the highlighted region of the Mask.

mutationObservables?: string[]

Array of CSS Selector that addition or removal will triggered a rerender of the Mask shape.

resizeObservables?: string[]

Array of CSS Selector that when resizeing each will triggered a rerender of the Mask shape.

navDotAriaLabel?: string

String to assign to aria-label attribute of the Dot of this step.

stepInteraction?: boolean

Allow to reenable the interaction for this specific step, when disableInteraction (from TourProvider) is true.

action?: (elem: Element | null) => void

Action fired when the Tour arrives in this step.

actionAfter?: (elem: Element | null) => void

Action fired when the Tour leaves this step.

disableActions?: boolean

Allow to disable all possible actions (interaction with Mask, Navigation Arrows, Navigation Dots, Close button and keyboard events) when the Tour is in this step.

padding?: Padding

Control padding spaces for this specific step.

bypassElem?: boolean

Excludes the main selector when calculating highlited area if present highlightedSelectors.

styles?: StylesObj & PopoverStylesObj & MaskStylesObj

Customize styles fro this specific step.

components?: PopoverComponentsType

Prop to customize granurally each Component inside the Popover.

Components available

| key | props | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Badge | styles | | Close | styles, onClick, disabled | | Content | content,setCurrentStep,transition, isHighlightingObserved,currentStep,setIsOpen | | Navigation | styles,setCurrentStep, steps, currentStep, disableDots, nextButton, prevButton, setIsOpen, hideButtons, hideDots, disableAll, rtl, Arrow, | | Arrow | styles, inverted, disabled |

import { components } from '@reactour/tour'

function Badge({ children }) {
  return (
    <components.Badge
      styles={{ badge: (base) => ({ ...base, backgroundColor: 'red' }) }}
    >
      👉 {children} 👈
    </components.Badge>
  )
}

function Close({ onClick }) {
  return (
    <button
      onClick={onClick}
      style={{ position: 'absolute', right: 0, top: 0 }}
    >
      x
    </button>
  )
}

const steps = [
  /* ... */
]

export default function App() {
  return (
    <TourProvider steps={steps} components={{ Badge, Close }}>
      {/* ... */}
    </TourProvider>
  )
}

styles?: StylesObj & PopoverStylesObj & MaskStylesObj

Prop to customize styles for the different parts of the Mask, Popover and Tour using a function that allows to extend the base styles an take advantage of some state props.

Style keys and props available

Refer to Mask docs and Popover docs for its specific Components

Tour Components

| key | props | | ---------- | ----------------------------------- | | badge | | | controls | | | button | disabled | | arrow | disabled | | dot | current, disabled, showNumber | | close | disabled |

const styles = {
  maskWrapper: (base) => ({
    ...base,
    color: 'red',
  }),
  highlightedArea: (base, { x, y }) => ({
    ...base,
    x: x + 10,
    y: y + 10,
  }),
  badge: (base) => ({ ...base, color: 'blue' }),
}

padding?: Padding

type Padding =
  | number
  | {
      mask?: ComponentPadding
      popover?: ComponentPadding
      wrapper?: ComponentPadding
    }

// x and y same value or [x, y] or [top, x, bottom] or [top, right, bottom, left]
type ComponentPadding = number | number[]

Extra space to add between the Mask and the Popover and the highlighted element. A single number coordinates both spaces. Otherwise, passing an Object specifying the Component space.

position?: Position

type Position =
  | 'top'
  | 'right'
  | 'bottom'
  | 'left'
  | 'center'
  | [number, number]
  | ((postionsProps: PositionProps) => Position)

type PositionProps = {
  bottom: number
  height: number
  left: number
  right: number
  top: number
  width: number
  windowWidth: number
  windowHeight: number
}

Set a global position for the Popover in all steps, fixed in case of [number, number], calculated in case of position string

setCurrentStep: Dispatch<React.SetStateAction<number>>

Function to control the Tour current step state.

currentStep: number

Custom Tour current step state.

This option could be overrided on specific steps using stepInteraction prop.

disableInteraction?: boolean | ((clickProps: Pick<ClickProps, 'currentStep' | 'steps' | 'meta'>) => boolean)

Disables the ability to click or interact in any way with the Highlighted element on every step.

This option could be overrided on specific steps using stepInteraction prop.

disableFocusLock?: boolean

The Tour uses FocusScope in order to lock the focus iteration inside the Popover when Tour is active. This prop allows to disable this behaviour.

disableDotsNavigation?: boolean

Disable interactivity with Dot navigation inside Popover.

disableWhenSelectorFalsy?: boolean

If true, don't show tours when selector or document.getElementById(step.selector) is falsy.

disableKeyboardNavigation?: boolean | KeyboardParts[]

type KeyboardParts = 'esc' | 'left' | 'right'

Disable all keyboard navigation events when true, disable only selected keys when array.

default: false

className?: string

Class assigned to Popover.

default: reactour__popover

maskClassName?: string

Class assigned to Mask.

default: reactour__mask

highlightedMaskClassName?: string

Class assigned to highlighted part of Mask. Useful when using disableInteraction.

nextButton?: (props: BtnFnProps) => void

prevButton?: (props: BtnFnProps) => void

type BtnFnProps = {
  Button: React.FC<NavButtonProps>
  setCurrentStep: Dispatch<React.SetStateAction<number>>
  stepsLength: number
  currentStep: number
  setIsOpen: Dispatch<React.SetStateAction<boolean>>
}

type NavButtonProps = {
  onClick?: () => void
  kind?: 'next' | 'prev'
  hideArrow?: boolean
}

Helper functions to customize the Next and Prev buttons inside Popover, with useful parameters. It is possible to use the base Button and customize the props.

afterOpen?: (target: Element | null) => void

Action fired just after the Tour is open.

beforeClose?: (target: Element | null) => void

Action fired just before the Tour is closed.

onClickMask?: (clickProps: ClickProps) => void

type ClickProps = {
  setIsOpen: Dispatch<React.SetStateAction<boolean>>
  setCurrentStep: Dispatch<React.SetStateAction<number>>
  setSteps: Dispatch<React.SetStateAction<StepType[]>>
  setMeta: Dispatch<React.SetStateAction<string>>
  currentStep: number
  steps: StepType[]
  meta: string
}

Function that overrides the default close behavior of the Mask click handler. Comes with useful parameters to play with.

onClickClose?: (clickProps: ClickProps) => void

type ClickProps = {
  setIsOpen: Dispatch<React.SetStateAction<boolean>>
  setCurrentStep: Dispatch<React.SetStateAction<number>>
  setSteps: Dispatch<React.SetStateAction<StepType[]>>
  setMeta: Dispatch<React.SetStateAction<string>>
  currentStep: number
  steps: StepType[]
  meta: string
}

Function that overrides the default close behavior of the Close icon click handler. Comes with useful parameters to play with.

onClickHighlighted?: (e: MouseEventHandler<SVGRectElement>, clickProps: ClickProps) => void

Click handler for highlighted area. Only works when disableInteraction is active. Useful in case is needed to avoid onClickMask when clicking the highlighted element.

<TourProvider
  steps={steps}
  disableInteraction
  onClickHighlighted={(e, clickProps) => {
    console.log('No interaction at all')
    if (clickProps.currentStep < 2) {
      e.stopPropagation()
      event.preventDefault()
      clickProps.setCurrentStep(
        Math.min(clickProps.currentStep + 1, clickProps.steps.length - 1)
      )
    }
  }}
>
  {/* ... */}
</TourProvider>
type ClickProps = {
  setIsOpen: Dispatch<React.SetStateAction<boolean>>
  setCurrentStep: Dispatch<React.SetStateAction<number>>
  setSteps: Dispatch<React.SetStateAction<StepType[]>>
  setMeta: Dispatch<React.SetStateAction<string>>
  currentStep: number
  steps: StepType[]
  meta: string
}

keyboardHandler?: KeyboardHandler

Function to handle keyboard events in a custom way.

type KeyboardHandler = {
  keyboardHandler?: (
    e: KeyboardEvent,
    clickProps?: ClickProps,
    status?: {
      isEscDisabled?: boolean
      isRightDisabled?: boolean
      isLeftDisabled?: boolean
    }
  ) => void
}
<TourProvider
  steps={steps}
  disableInteraction
  keyboardHandler={(e, clickProps) => {
    if (e.key === 'ArrowRight') {
      clickProps.setCurrentStep(
        Math.min(clickProps.currentStep + 1, clickProps.steps.length - 1)
      )
    }
    if (e.key === 'ArrowLeft') {
      clickProps.setCurrentStep(Math.max(clickProps.currentStep - 1, 0))
    }
    if (e.key === 'Escape') {
      const nextStep = Math.floor(Math.random() * clickProps.steps.length)
      clickProps.setCurrentStep(nextStep)
    }
  }}
>
  {/* ... */}
</TourProvider>

badgeContent?: (badgeProps: BadgeProps) => any

type BadgeProps = {
  totalSteps: number
  currentStep: number
  transition: boolean
}

Function to customize the content of the Badge using helper parameters like the current and total steps and if the Tour is transitioning between steps.

showNavigation?: boolean

Show or hide the Navigation (Prev and Next buttons and Dots) inside Popover.

showPrevNextButtons?: boolean

Show or hide Prev and Next buttons inside Popover.

showCloseButton?: boolean

Show or hide the Close button inside Popover.

showBadge?: boolean

Show or hide the Badge inside Popover.

showDots?: boolean

Show or hide dots navigation inside Popover.

scrollSmooth?: boolean

Activate smooth scroll behavior when steps are outside viewport.

default: false

inViewThreshold?: { x?: number, y?: number } | number

Tolerance in pixels to add when calculating if the step element is outside viewport to scroll into view.

accessibilityOptions?: A11yOptions

type A11yOptions = {
  ariaLabelledBy: string
  closeButtonAriaLabel: string
  showNavigationScreenReaders: boolean
}

Configure generic accessibility related attributes like aria-labelledby, aria-label for Close button and if show or hide Dot navigation in screen readers.

rtl?: boolean

Option to navigate and show Navigation in right-to-left mode

maskId?: string

Mask ID to pass directly into the Mask component

clipId?: string

Clip ID to pass directly into the Mask component

onTransition?: PositionType

Function to control the behavior of Popover when is transitioning/scrolling from one step to another, calculating with Popover next position and previous one

type PositionType = (
  postionsProps: PositionProps,
  prev: RectResult
) => 'top' | 'right' | 'bottom' | 'left' | 'center' | [number, number]

ContentComponent?: ComponentType<PopoverContentProps>

Completelly custom component to render inside the Popover.

type PopoverContentProps = {
  styles?: StylesObj & PopoverStylesObj & MaskStylesObj
  badgeContent?: (badgeProps: BadgeProps) => any
  components?: PopoverComponentsType
  accessibilityOptions?: A11yOptions
  disabledActions?: boolean
  onClickClose?: (clickProps: ClickProps) => void
  setCurrentStep: Dispatch<React.SetStateAction<number>>
  currentStep: number
  transition?: boolean
  isHighlightingObserved?: boolean
  setIsOpen: Dispatch<React.SetStateAction<boolean>>
  steps: StepType[]
  showNavigation?: boolean
  showPrevNextButtons?: boolean
  showCloseButton?: boolean
  showBadge?: boolean
  nextButton?: (props: BtnFnProps) => void
  prevButton?: (props: BtnFnProps) => void
  disableDotsNavigation?: boolean
  rtl?: boolean
}
function ContentComponent(props) {
  const isLastStep = props.currentStep === props.steps.length - 1
  const content = props.steps[props.currentStep].content
  return (
    <div style={{ border: '5px solid red', padding: 10, background: 'white' }}>
      {/* Check if the step.content is a function or a string */}
      {typeof content === 'function'
        ? content({ ...props, someOtherStuff: 'Custom Text' })
        : content}
      <button
        onClick={() => {
          if (isLastStep) {
            props.setIsOpen(false)
          } else {
            props.setCurrentStep((s) => s + 1)
          }
        }}
      >
        {isLastStep ? 'x' : '>'}
      </button>
    </div>
  )
}

const steps = [
  /* ... */
]

function App() {
  return (
    <TourProvider
      steps={steps}
      ContentComponent={ContentComponent}
      styles={{ popover: (base) => ({ ...base, padding: 0 }) }}
    >
      {/* ... */}
    </TourProvider>
  )
}

Wrapper?: ComponentType

Element which wraps the Tour, useful in case is needed to port the Tour into a Portal. Defaults to React.Fragment

useTour

Later in any Component down in the tree of TourProvider you can control the Tour in many ways

import { useTour } from '@reactour/tour'

function MyComponent() {
  const { isOpen, currentStep, steps, setIsOpen, setCurrentStep, setSteps } = useTour()
  return (
    <>
      <h1>{isOpen ? 'Welcome to the tour!' : 'Thank you for participate!'}</h1>
      <p>
        Now you are visiting the place {currentStep + 1} of {steps.length}
      </p>
      <nav>
        <button onClick={() => setIsOpen(o => !o)}>Toggle Tour</button>
        <button onClick={() => setCurrentStep(3)}>
          Take a fast way to 4th place
        </button>
        <button
          onClick={() =>
            setSteps([
              { selector: '.new-place-1', content: 'New place 1' },
              { selector: '.new-place-2', content: 'New place 2' },
            ])
            setCurrentStep(1)
          }
        >
          Switch to a new set of places, starting from the last one!
        </button>
      </nav>
    </>
  )
}

isOpen: boolean

Is the Tour open or close

currentStep: number

The current step. zero based

steps: StepType[]

The Array of steps set currently

setIsOpen: Dispatch<React.SetStateAction<boolean>>

SetState function open or close Tour

setSteps: Dispatch<React.SetStateAction<StepType[]>>

SetState function to update the Array of steps.

meta: string

Global meta information that could be useful in complex Tour/s situtations

setMeta: Dispatch<React.SetStateAction<string>>

SetState function to update the global meta info.

Warning: Make sure you reset the currentStep value using the setCurrentStep function to ensure the tour will be opened to the correct step after update. Otherwise, in case where a person has already interacted with the tour steps and closed the tours on step 5 for example, they might open to the incorrect step, or similarly if the new set of steps only has 3 steps nothing will open.

withTour

In case you needed there is an enhancer that allows you to have all useTour functionalities through a Higher Order Component.

import { Component } from 'react'
import { withTour } from '@reactour/tour'

class MyComponent extends Component {
  render() {
    return (
      <>
        <button onClick={() => this.props.setIsOpen(true)}>Start Tour</button>
        <div>{/* ... */}</div>
      </>
    )
  }
}

export default withTour(MyCompnent)