Tourist Guide into your React Components
This documentation is for the latest release, which uses npm scoped package
@reactour
. The originalreactour
is now on branchv1
and its documentation can be found here.
npm i -S @reactour/tour
# or
yarn add @reactour/tour
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>
</>
)
}
The Playground is the perfect place to play aroud with all @reactour
Components. Here is an online version.
- Using React Router
- Using React Router with automatic route switching
- Using React Modal
- Using Semantic UI Modal
- Using React Bootstrap Modal
- Tour with data fetching
Feel free to make a PR proposing new sandboxes or demos to add in the playground.
Array of elements to highlight with special info and props.
StepType
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.
The preferred postion to position the Popover in relation with the highlighted element. Will be automatically calculated in case of unavailable space.
Array of CSS Selector to be included (by union) in the highlighted region of the Mask.
Array of CSS Selector that addition or removal will triggered a rerender of the Mask shape.
Array of CSS Selector that when resizeing each will triggered a rerender of the Mask shape.
String to assign to aria-label
attribute of the Dot of this step.
Allow to reenable the interaction for this specific step, when disableInteraction
(from TourProvider) is true
.
Action fired when the Tour arrives in this step.
Action fired when the Tour leaves this step.
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.
Control padding spaces for this specific step.
Excludes the main selector
when calculating highlited area if present highlightedSelectors
.
Customize styles fro this specific step.
Prop to customize granurally each Component inside the Popover.
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
|
Example
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>
)
}
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.
Refer to Mask docs and Popover docs for its specific Components
key | props |
---|---|
badge |
|
controls |
|
button |
disabled |
arrow |
disabled |
dot |
current , disabled , showNumber
|
close |
disabled |
Example
const styles = {
maskWrapper: (base) => ({
...base,
color: 'red',
}),
highlightedArea: (base, { x, y }) => ({
...base,
x: x + 10,
y: y + 10,
}),
badge: (base) => ({ ...base, color: 'blue' }),
}
Type details
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.
Type details
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
Function to control the Tour current step state.
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.
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.
Disable interactivity with Dot navigation inside Popover.
If true, don't show tours when selector
or document.getElementById(step.selector)
is falsy.
Type details
type KeyboardParts = 'esc' | 'left' | 'right'
Disable all keyboard navigation events when true
, disable only selected keys when array.
default: false
Class assigned to Popover.
default: reactour__popover
Class assigned to Mask.
default: reactour__mask
Class assigned to highlighted part of Mask. Useful when using disableInteraction
.
Type details
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.
Action fired just after the Tour is open.
Action fired just before the Tour is closed.
Type details
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.
Type details
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.
Click handler for highlighted area. Only works when disableInteraction
is active. Useful in case is needed to avoid onClickMask
when clicking the highlighted element.
Example
<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 details
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 to handle keyboard events in a custom way.
Type details
type KeyboardHandler = {
keyboardHandler?: (
e: KeyboardEvent,
clickProps?: ClickProps,
status?: {
isEscDisabled?: boolean
isRightDisabled?: boolean
isLeftDisabled?: boolean
}
) => void
}
Example
<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>
Type details
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.
Show or hide the Navigation (Prev and Next buttons and Dots) inside Popover.
Show or hide Prev and Next buttons inside Popover.
Show or hide the Close button inside Popover.
Show or hide the Badge inside Popover.
Show or hide dots navigation inside Popover.
Activate smooth
scroll behavior when steps are outside viewport.
default: false
Tolerance in pixels to add when calculating if the step element is outside viewport to scroll into view.
Type details
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.
Option to navigate and show Navigation in right-to-left mode
Mask ID to pass directly into the Mask component
Clip ID to pass directly into the Mask component
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 details
type PositionType = (
postionsProps: PositionProps,
prev: RectResult
) => 'top' | 'right' | 'bottom' | 'left' | 'center' | [number, number]
Completelly custom component to render inside the Popover.
Type details
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
}
Example
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>
)
}
Element which wraps the Tour, useful in case is needed to port the Tour into a Portal. Defaults to React.Fragment
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>
</>
)
}
Is the Tour open or close
The current step. zero based
The Array
of steps set currently
SetState
function open or close Tour
SetState
function to update the Array
of steps.
Global meta information that could be useful in complex Tour/s situtations
SetState
function to update the global meta info.
Warning: Make sure you reset the
currentStep
value using thesetCurrentStep
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.
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)