Skip to Content

Usage

Basic Example

Currently, the TourComponent is in the Navbar so we just provide the files and routeFileLinks props to the Navbar.

import TourComponent from "./TourComponent"; const Navbar: FC<Props> = ({ files, routeFileLinks }) => { return ( <> ... <TourComponent id={getFQCN(fqcnBUI, "tour-component")} files={files} routeFileLinks={routeFileLinks} /> </> ); };

Ref : https://github.com/PHPCreation/phpreaction-frontend-pointofsale-react/blob/main/src/app/%5Blocale%5D/layout.tsx 

export default async function Layout({ children, }: Readonly<{ children: React.ReactNode; }>) { const files: ToursFiles = { products: [ { name: "Intro", filePath: "intro" }, { name: "Advanced", filePath: "advanced" } ], lines: [ { name: "Intro", filePath: "intro" }, { name: "Fields", filePath: "fields" } ] }; const routeFileLinks = [ { pattern: "^.*/products$", folderName: "products" }, { pattern: "^.*/lines$", folderName: "lines" }, ]; return ( <html lang="en" suppressHydrationWarning> <body > <Navbar ... files={files} routeFileLinks={routeFileLinks} /> {children} </body> </html> ); }

Props

id (optional)

  • Type: string
  • Description: PFQCN identifier for the tour instance
  • Example: "dashboard-tour"
  • Type: Array<{ pattern: string; folderName: string }>
  • Description: Maps route patterns to tour folder names. Patterns are converted to RegExp.
  • Example:
[ { pattern: `^.*\/invoice$`, folderName: "invoice" }, { pattern: `^.*\/lines$`, folderName: "lines" }, { pattern: `^/product/\\d+$`, folderName: "product_show" }, ];

files (optional)

  • Type: ToursFiles - { [key: string]: Array<{ name: string; filePath: string }> }
  • Description: Object mapping folder names to arrays of tour files.
  • Note: The name is a translation key for the dropdown so make sure to provide appropriate i18n keys.
  • Example:
{ products: [ { name: "Intro", filePath: "intro" }, { name: "Advanced", filePath: "advanced" } ], lines: [ { name: "Intro", filePath: "intro" }, { name: "Fields", filePath: "fields" } ] }

Tour File Structure

Tour files should be JSON files placed in the /public/tours_list/ directory.

Single-Page Tour

Ex: https://github.com/PHPCreation/phpreaction-frontend-pointofsale-react/blob/main/public/tours_list/invoice/intro.json 

Each step will have this step structure

Note: The content is a translation key.

[ { "target": "#pfqcn_phprconfig_pos_invoice_container_main", "content": "invoice.full.step0", "disableScrolling": true }, { "target": "#pfqcn_phprconfig_pos_invoice_form_date_calendar", "content": "invoice.full.step1", "placement": "top" } ]

Multi-Page Tour

Ex: https://github.com/PHPCreation/phpreaction-frontend-pointofsale-react/blob/main/public/tours_list/invoice/full_app.json 

It starts with a special configuration step indicating it’s a multi-page tour: multiPage.

The other steps include :

  • tour: Path to the tour file from /public/tours_list/ (e.g., dashboard/intro_tour)
  • url: RegExp pattern for the target page URL
[ { "multiPage": true }, { "tour": "dashboard/page1_tour", "url": "^/dashboard$" }, { "tour": "settings/page2_tour", "url": "^/settings$" } ]

Multi-Tour Same Page

Ex: https://github.com/PHPCreation/phpreaction-frontend-pointofsale-react/blob/main/public/tours_list/invoice/test_multiple.json 

It starts with a special configuration step indicating it’s a multi-tour same page tour : multiTourSamePage.

The other steps include :

  • tour: Path to the tour file from /public/tours_list/ (e.g., dashboard/intro_tour)
[ { "multiTourSamePage": true }, { "tour": "dashboard/section1" }, { "tour": "dashboard/section2" } ]

Step Configuration

It’ll have the same structure as the Joyride steps 

Here are the commonly used properties:

Required Properties

  • target: CSS selector for the element to highlight
  • content: Text or HTML string to display (supports i18n keys)

Optional Properties

  • title: Heading text for the tooltip
  • placement: Tooltip position - "top", "bottom", "left", "right", "center", "auto"
  • data: Custom data object
    • hideNextButton: Set to true to hide the Next button on last step (This is important when user action is required to go to next tour. E.g., filling a form, clicking a button and being redirected by the app, etc.)

Example Step

{ "target": "#feature-card", "content": "tour.dashboard.feature_explanation", "title": "tour.dashboard.feature_title", "placement": "right", "data": { "hideNextButton": false } }

Keyboard Shortcuts

When a tour is active:

  • Right Arrow (→): Next step
  • Left Arrow (←): Previous step
  • ESC: Close tour (via Joyride default)

URL Parameters

Start a tour automatically using query string parameters:

  • tour_file: Path to the tour file from /public/tours_list/ (e.g., dashboard/intro_tour)
  • tour_step (optional): Step number to start from (1-based index). Defaults to 1 if not provided.

Example:

https://example.com/dashboard?tour_file=dashboard/intro_tour&tour_step=3

State Persistence

Multi-page tours use localStorage to persist state:

  • Key: "multiPageTours"
  • Value: Array of remaining tours
  • Cleanup: Automatically cleared when full tour completes or is closed

Custom Tooltip

Ref : https://github.com/PHPCreation/frontend-components-react-nextjs-bundle/tree/main/src/components/Tour/CustomTooltip/index.tsx 

The component includes a custom tooltip (CustomTooltip) with:

  • Close button (✕)
  • Title display
  • Content area (supports HTML)
  • Back button (hidden on first step)
  • Progress indicator with shareable link
  • Next/Finish button

Each tooltip includes a progress indicator that is also a shareable link:

<Link href={"?tour_file=" + step.tourFile + "&tour_step=" + (index + 1)}> {index + 1} / {size} </Link>

Users can click on the progress indicator to share direct links to specific tour steps.

Styling

The component uses Tailwind CSS classes. Customize the appearance by:

Advanced Patterns

Conditional Next Button

Hide the Next button on the last step when user action is required:

{ "target": "#action-button", "content": "Click this button to proceed", "data": { "hideNextButton": true } }

Dynamic Content Loading

Tour content is fetched dynamically from:

{window.location.origin}/tours_list/{tourFilePath}.json

Ensure your tour files are publicly accessible.

Best Practices

  • Organize tour files: Use clear folder structures matching your app routes
  • Provide translations: Always use i18n keys for content that may need localization
  • Limit step count: Keep tours concise (5-10 steps per tour is ideal)
Last updated on