@reactour/tour

Here are the examples for the Tour package

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>
  )
}

onClickMaskDocs

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>
  )
}

onClickCloseDocs

Disable Keyboard

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 { 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>
    </>
  )
}

disableKeyboardNavigationDocs

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>
  )
}

scrollSmoothDocs

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>
  )
}

paddingDocs

Custom 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>
  )
}

prevButtonDocsnextButtonDocs

Custom handlers

Control currenStep 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>
  )
}

setCurrentStepDocscurrentStepDocs

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>
  )
}

rtlDocs

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>
  )
}

stylesDocs

Disable Scroll

In this example, we are using afterOpen prop to lock the Y scroll and re-enable it through beforeCloseprop.
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>
  )
}

afterOpenDocsbeforeCloseDocs

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>
  )
}

badgeContentDocs

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>
  )
}

disableDotsNavigationDocs

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>
  )
}

disableInteractionDocs

Toggle navigation parts

Toggle Navigation parts as you want
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>
    </>
  )
}

showBadgeDocsshowCloseButtonDocsshowNavigationDocsshowPrevNextButtonsDocsshowDotsDocs

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>
  )
}