Skip to main content

Wizard (Driver)

A component to guide the user's focus across the page with interactive tours.

Package@g4rcez/componentsSectionFloating Elements

Examples

Basic Page Tour

Demonstrates a multi-step tour that highlights elements on the page using various selection methods (ID, Ref).

Driver Demo

Step 1 Target

ID: #step-1

Ignored Element

This element is not part of the tour.

Step 3 Target

ID: #step-3

tsx
"use client";
import { useRef, useState } from "react";
import { Button, Card, Wizard, WizardStep } from "@g4rcez/components";
import { Tag } from "@g4rcez/components/tag";

function BasicPageTour() {
  const [active, setActive] = useState(false);
  const buttonRef = useRef(null);

  const steps: WizardStep[] = [
    {
      element: "#step-1",
      title: "First Step (ID Selector)",
      description: "This element is selected using a CSS selector string '#step-1'.",
      side: "right",
    },
    {
      element: buttonRef,
      title: (
        <span className="flex gap-2 items-center">
          React Node Title <Tag size="small">New</Tag>
        </span>
      ),
      description: (
        <div className="flex flex-col gap-2">
          <span>This description uses a React Node.</span>
          <span className="text-xs text-info">You can put anything here!</span>
        </div>
      ),
      side: "bottom",
    },
    {
      element: "#step-3",
      title: "Third Step",
      description: "Back to ID selector.",
      side: "top",
      onEnter: () => console.log("Entered step 3"),
    },
  ];

  return (
    <Card title="Driver Demo">
      <Button onClick={() => setActive(true)}>Start Tour</Button>
      <div className="grid grid-cols-1 gap-8 mt-8 md:grid-cols-2">
        <div
          id="step-1"
          className="p-8 rounded-lg border border-card-border bg-card-background"
        >
          <h3 className="font-bold">Step 1 Target</h3>
          <p className="">ID: #step-1</p>
        </div>
        <div className="p-8 rounded-lg border opacity-50 border-card-border bg-card-background">
          <h3 className="font-bold">Ignored Element</h3>
          <p>This element is not part of the tour.</p>
        </div>
        <div className="flex justify-center items-center p-8 rounded-lg border border-card-border bg-card-background">
          <Button ref={buttonRef}>Step 2 Target (Ref)</Button>
        </div>
        <div
          id="step-3"
          className="p-8 text-right rounded-lg border border-card-border bg-card-background"
        >
          <h3 className="font-bold">Step 3 Target</h3>
          <p className="">ID: #step-3</p>
        </div>
      </div>
      <Wizard
        steps={steps}
        active={active}
        onClose={() => setActive(false)}
        onFinish={() => alert("Tour finished!")}
      />
    </Card>
  );
}

Wizard with Modal Integration

Demonstrates how the Wizard component integrates seamlessly with Modals, appearing above the modal's overlay with correct z-index.

Wizard + Modal Integration

Start a tour on the page, then let the Wizard open the Modal and highlight content inside it.

tsx
"use client";
import { useState } from "react";
import { Button, Card, Modal, Wizard, WizardStep } from "@g4rcez/components";

function ModalWizardIntegration() {
  const [modalOpen, setModalOpen] = useState(false);
  const [modalWizardActive, setModalWizardActive] = useState(false);

  const closeModalWizard = () => {
    setModalWizardActive(false);
    setModalOpen(false);
  };

  const changeModalOpen = (open: boolean) => {
    setModalOpen(open);
    if (!open) {
      setModalWizardActive(false);
    }
  };

  const modalSteps: WizardStep[] = [
    {
      element: "#modal-tour-trigger",
      title: "Start outside the modal",
      description: "This tour starts on the page, then opens a modal for the next step.",
      side: "bottom",
    },
    {
      element: "#modal-step-1",
      title: "Modal Content",
      description: "This step opens the modal and highlights content inside it.",
      side: "bottom",
      onEnter: () => setModalOpen(true),
    },
    {
      element: "#modal-step-2",
      title: "Action Button",
      description: "You can guide users through modal interactions.",
      side: "top",
    },
  ];

  return (
    <Card title="Wizard + Modal Integration">
      <p className="mb-4">
        Start a tour on the page, then let the Wizard open the Modal and highlight content inside it.
      </p>
      <Button
        id="modal-tour-trigger"
        onClick={() => {
          setModalOpen(false);
          setModalWizardActive(true);
        }}
      >
        Start Tour That Opens Modal
      </Button>
      <Modal
        closable
        open={modalOpen}
        type="dialog"
        title="Modal with Wizard Tour"
        overlayClickClose
        onChange={changeModalOpen}
      >
        <div className="flex flex-col gap-4">
          <p
            id="modal-step-1"
            className="p-4 rounded-lg border border-card-border bg-card-muted"
          >
            This is the modal content. The Wizard should appear above this modal overlay.
          </p>
          <div className="flex gap-2">
            <Button id="modal-step-2">Confirm action</Button>
            <Button theme="neutral" onClick={closeModalWizard}>
              Close
            </Button>
          </div>
        </div>
      </Modal>
      <Wizard
        steps={modalSteps}
        active={modalWizardActive}
        onClose={closeModalWizard}
        onFinish={() => {
          closeModalWizard();
          alert("Modal tour finished!");
        }}
      />
    </Card>
  );
}

When to use Wizard (Driver)

Use when

You need the documented Wizard (Driver) interaction or presentation in a product workflow.

Avoid when

A native HTML element already provides the Wizard (Driver) behavior you need.

Accessibility

Keep the Wizard (Driver) labeled and use its documented keyboard interaction. The component preserves visible focus and communicates state without relying on color alone.

  • Keep keyboard focus visible and follow the documented key commands.
  • Provide an accessible name and connect descriptions or errors to the control.