Tour
Examples

@reactour/tour examples

Basic example

This is the minimal example

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider steps={steps}>
      <Main />
    </TourProvider>
  )
}

Mask click

Example to show the customizable behavior of the Mask click event. Try clicking the Mask and the Tour will proceed to the next step.

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider 
      steps={steps}
      onClickMask={({ setCurrentStep, currentStep, steps, setIsOpen }) => {
        if (steps) {
          if (currentStep === steps.length - 1) {
            setIsOpen(false)
          }
          setCurrentStep((s) => (s === steps.length - 1 ? 0 : s + 1))
        }
      }}>
      <Main />
    </TourProvider>
  )
}

Close click

Example to show the customizable behavior of the Close click event. Try clicking the 'x' and the Tour will proceed to the next step.

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider 
      steps={steps}
      onClickClose={({ setCurrentStep, currentStep, steps, setIsOpen }) => {
        if (steps) {
          if (currentStep === steps.length - 1) {
            setIsOpen(false)
          }
          setCurrentStep((s) => (s === steps.length - 1 ? 0 : s + 1))
        }
      }}>
      <Main />
    </TourProvider>
  )
}

Disable Keyboard

Example to show how to disable keyboard behavior.

import { TourProvider } from '@reactour/tour'
import { useState } from 'react'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  const [disableKeyboardNavigation, setDisable] = useState([
    'esc',
  ])

  function onChange(event) {
    let updatedList = [...disableKeyboardNavigation];
    if (event.target.checked) {
      updatedList = [...disableKeyboardNavigation, event.target.value];
    } else {
      updatedList.splice(disableKeyboardNavigation.indexOf(event.target.value), 1);
    }
    setDisable(updatedList);
  }

  return (
    <>
      <pre className="demo-selectors">
        <code>Disabled keys: 
          <label>
            <input 
            type="checkbox" 
            name="dk" 
            value="left" 
            onChange={onChange} 
            checked={disableKeyboardNavigation.includes("left")} /> left
          </label>
          <label>
            <input 
            type="checkbox" 
            name="dk" 
            value="right" 
            onChange={onChange} 
            checked={disableKeyboardNavigation.includes("right")} /> right
          </label>
          <label>
            <input 
            type="checkbox" 
            name="dk" 
            value="esc" 
            onChange={onChange} 
            checked={disableKeyboardNavigation.includes("esc")} /> esc
          </label>
        </code>
      </pre>
      <TourProvider 
        steps={steps}
        disableKeyboardNavigation={disableKeyboardNavigation}
      >
        <Main />
      </TourProvider>
    </>
  )
}

Scroll Smooth

Use smooth scroll between steps if they aren't visible in viewport

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider steps={steps} scrollSmooth>
      <Main />
    </TourProvider>
  )
}

Padding

Custom wrapper, mask and popover paddings

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider 
      steps={steps} 
      padding={{ 
        mask: 14, 
        popover: [5, 10], 
        wrapper: 20 
      }}
    >
      <Main />
    </TourProvider>
  )
}

Prev and Next buttons

Custom Prev and Next button

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider 
      steps={steps} 
      prevButton={({ currentStep, setCurrentStep, steps }) => {
        const first = currentStep === 0
        return (
          <button
            onClick={() => {
              if (first) {
                setCurrentStep((s) => steps.length - 1)
              } else {
                setCurrentStep((s) => s - 1)
              }
            }}
          >
            Back
          </button>
        )
      }}
      nextButton={({
        Button,
        currentStep,
        stepsLength,
        setIsOpen,
        setCurrentStep,
        steps,
      }) => {
        const last = currentStep === stepsLength - 1
        return (
            <Button
              onClick={() => {
                  if (last) {
                    setIsOpen(false)
                  } else {
                    setCurrentStep((s) => (s === steps?.length - 1 ? 0 : s + 1))
                  }
              }}
            >
              {last ? 'Close!' : null}
            </Button>
        )
      }}
    >
      <Main />
    </TourProvider>
  )
}

Custom handlers

Control currentStep externally. Useful when using global state.

import { useState } from 'react'
import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  const [currentStep, setCurrentStep] = useState(0)
  console.log(currentStep)
  return (
    <TourProvider 
      steps={steps} 
      currentStep={currentStep}
      setCurrentStep={() => {
        if (currentStep === steps.length - 1) {
            setCurrentStep(0)    
        } else {
            setCurrentStep(currentStep + 1)
        }
      }}
    >
      <Main />
    </TourProvider>
  )
}

RTL

RTL mode

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider steps={steps} rtl>
      <Main />
    </TourProvider>
  )
}

Custom styles

Custom Tour, Mask and Popover components and parts styles

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  const radius = 10
  
  return (
    <TourProvider 
      steps={steps} 
      styles={{
        popover: (base) => ({
          ...base,
          '--reactour-accent': '#ef5a3d',
          borderRadius: radius,
        }),
        maskArea: (base) => ({ ...base, rx: radius }),
        maskWrapper: (base) => ({ ...base, color: '#ef5a3d' }),
        badge: (base) => ({ ...base, left: 'auto', right: '-0.8125em' }),
        controls: (base) => ({ ...base, marginTop: 100 }),
        close: (base) => ({ ...base, right: 'auto', left: 8, top: 8 }),
      }}
    >
      <Main />
    </TourProvider>
  )
}

Disable Scroll

In this example, we are using afterOpen prop to lock the Y scroll and re-enable it through beforeClose prop.

import { TourProvider } from '@reactour/tour'
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  const disableBody = (target) => disableBodyScroll(target)
  const enableBody = (target) => enableBodyScroll(target)
  return (
    <TourProvider steps={steps} afterOpen={disableBody} beforeClose={enableBody}>
      <Main />
    </TourProvider>
  )
}

Custom Badge

Create a custom Badge content

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider 
      steps={steps}
      badgeContent={({ totalSteps, currentStep }) => currentStep + 1 + "/" + totalSteps}
    >
      <Main />
    </TourProvider>
  )
}

Disable dots navigation

Disable navigating through click in dots buttons

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider steps={steps} disableDotsNavigation>
      <Main />
    </TourProvider>
  )
}

Disable interaction

Disable highlighted area interaction. This example shows how to disable the default behavior and how to add an extra functionality when clicking this area. Try to select the highlighted text.

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider 
      steps={steps} 
      onClickHighlighted={(e) => {
        e.stopPropagation()
        console.log('No interaction')
      }} 
      disableInteraction
      >
      <Main />
    </TourProvider>
  )
}

Toggle navigation parts

Toggle Navigation parts as you want: badge, close button, prev & next buttons, dots or whole navigation zone.

import { TourProvider } from '@reactour/tour'
import { useState } from 'react'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  const [enabledParts, setEnabled] = useState([
    'badge','close','nav','buttons','dots'
  ])

  function onChange(event) {
    let updatedList = [...enabledParts];
    if (event.target.checked) {
      updatedList = [...enabledParts, event.target.value];
    } else {
      updatedList.splice(enabledParts.indexOf(event.target.value), 1);
    }
    setEnabled(updatedList);
  }

  return (
    <>
      <pre className="demo-selectors column">
        <code>Enabled parts: 
          <label>
            <input 
            type="checkbox" 
            name="dk" 
            value="badge" 
            onChange={onChange} 
            checked={enabledParts.includes("badge")} /> badge
          </label>
          <label>
            <input 
            type="checkbox" 
            name="dk" 
            value="close" 
            onChange={onChange} 
            checked={enabledParts.includes("close")} /> close button
          </label>
          <label>
            <input 
            type="checkbox" 
            name="dk" 
            value="nav" 
            onChange={onChange} 
            checked={enabledParts.includes("nav")} /> navigation
          </label>
          <label>
            <input 
            type="checkbox" 
            name="dk" 
            value="buttons" 
            onChange={onChange} 
            checked={enabledParts.includes("buttons")} /> prev & next buttons
          </label>
          <label>
            <input 
            type="checkbox" 
            name="dk" 
            value="dots" 
            onChange={onChange} 
            checked={enabledParts.includes("dots")} /> dots
          </label>
        </code>
      </pre>
      <TourProvider 
        steps={steps}
        showBadge={enabledParts.includes('badge')}
        showCloseButton={enabledParts.includes('close')}
        showNavigation={enabledParts.includes('nav')}
        showPrevNextButtons={enabledParts.includes('buttons')}
        showDots={enabledParts.includes('dots')}
      >
        <Main />
      </TourProvider>
    </>
  )
}

Starts at

Start Tour at specific step. Keep in mind that the number is zero based, so 2 is the third step.

import { TourProvider } from '@reactour/tour'
import { steps } from './steps.js'
import Main from './Main.js'
	
export default function App () {
  return (
    <TourProvider steps={steps} startAt={2}>
      <Main />
    </TourProvider>
  )
}