## Component Name

SpotlightPopoverTour

## Description

The SpotlightPopoverTour component is used to provide context as well as enable users to take certain actions on it. These are used to highlight a new feature or provide a guided tour to a new user. The component can spotlight specific UI elements on the page and present a series of steps with descriptions.

## TypeScript Types

Below are the TypeScript types that define the props that the SpotlightPopoverTour and its subcomponents accept:

```typescript
// Main component props
type SpotlightPopoverTourProps = {
  /**
   * Array of steps to be rendered
   *
   * The order of the steps will be the order in which they are rendered depending on the `activeStep` prop
   */
  steps: SpotlightPopoverTourSteps;
  /**
   * Whether the tour is visible or not
   */
  isOpen: boolean;
  /**
   * Callback when the tour is opened or closed
   */
  onOpenChange?: ({ isOpen }: { isOpen: boolean }) => void;
  /**
   * Callback which fires when the `stopTour` method is called from the `steps` array
   */
  onFinish?: () => void;
  /**
   * Callback when the active step changes
   */
  onStepChange?: (step: number) => void;
  /**
   * Active step to be rendered
   */
  activeStep: number;
  children: React.ReactNode;
};

// Tour step props
type SpotlightPopoverTourStepProps = {
  name: string;
  children: React.ReactNode;
};

// Tour step definition
type Step = {
  /**
   * Unique identifier for the tour step
   */
  name: string;
  /**
   * Content of the Popover
   */
  content: (props: SpotlightPopoverStepRenderProps) => React.ReactElement;
  /**
   * Footer content
   */
  footer?: (props: SpotlightPopoverStepRenderProps) => React.ReactNode;
  /**
   * Popover title
   */
  title?: string;
  /**
   * Leading content placed before the title
   *
   * Can be any blade icon or asset.
   */
  titleLeading?: React.ReactNode;
  /**
   * Placement of Popover
   * @default "top"
   */
  placement?: UseFloatingOptions['placement'];
};

// Array of Step objects
type SpotlightPopoverTourSteps = Step[];

// Props passed to render functions
type SpotlightPopoverStepRenderProps = {
  /**
   * Go to a specific step
   */
  goToStep: (step: number) => void;
  /**
   * Go to the next step
   */
  goToNext: () => void;
  /**
   * Go to the previous step
   */
  goToPrevious: () => void;
  /**
   * Stop the tour
   *
   * This will call the `onFinish` callback
   */
  stopTour: () => void;
  /**
   * Current active step (zero based index)
   */
  activeStep: number;
  /**
   * Total number of steps
   */
  totalSteps: number;
};
```

## Example

### Basic Tour Example

This example demonstrates a simple guided tour with three steps highlighting different UI elements, using a custom footer component to control navigation between steps.

```jsx
import { useState } from 'react';
import {
  SpotlightPopoverTour,
  SpotlightPopoverTourStep,
  SpotlightPopoverTourFooter,
  Box,
  Button,
  Text,
  Card,
  CardBody,
  InfoIcon,
  Amount,
} from '@razorpay/blade/components';

function BasicTourExample() {
  const [activeStep, setActiveStep] = useState(0);
  const [isOpen, setIsOpen] = useState(false);

  // Custom footer component that can control the tour
  const CustomTourFooter = ({ activeStep, totalSteps, goToNext, goToPrevious, stopTour }) => {
    const isLast = activeStep === totalSteps - 1;
    const isFirst = activeStep === 0;

    return (
      <SpotlightPopoverTourFooter
        activeStep={activeStep}
        totalSteps={totalSteps}
        actions={{
          primary: isLast
            ? {
                text: 'Done',
                onClick: stopTour,
              }
            : {
                text: 'Next',
                onClick: goToNext,
              },
          secondary: isFirst
            ? undefined
            : {
                text: 'Prev',
                onClick: goToPrevious,
              },
        }}
      />
    );
  };

  // Define the tour steps
  const steps: SpotlightPopoverTourSteps = [
    {
      name: 'refunds-step',
      title: 'Overview of Refunds',
      content: () => (
        <Box>
          <Text color="surface.text.gray.subtle">
            You can issue refunds for various reasons, like when a customer returns a product or
            cancels a service.
          </Text>
          <Text color="surface.text.gray.subtle" marginTop="spacing.2">
            You can also issue partial refunds - for example, if a customer purchased multiple
            items.
          </Text>
        </Box>
      ),
      placement: 'bottom' as const,
      footer: CustomTourFooter,
    },
    {
      name: 'disputes-step',
      title: 'Overview of Disputes',
      content: () => (
        <Box>
          <Text color="surface.text.gray.subtle">
            Disputes are raised by customers when they have a problem with a transaction.
          </Text>
        </Box>
      ),
      placement: 'bottom' as const,
      footer: CustomTourFooter,
    },
    {
      name: 'status-step',
      title: 'Dispute Statuses',
      content: () => (
        <Text color="surface.text.gray.subtle">
          Disputes which are open or under review will be shown here. You can also review them by
          clicking on the button.
        </Text>
      ),
      placement: 'bottom' as const,
      footer: CustomTourFooter,
    },
  ];

  return (
    <Box>
      <Button
        marginBottom="spacing.9"
        onClick={() => {
          setIsOpen(!isOpen);
        }}
      >
        {isOpen ? 'Tour In Progress' : 'Start Tour'}
      </Button>

      <SpotlightPopoverTour
        steps={steps}
        isOpen={isOpen}
        activeStep={activeStep}
        onFinish={() => {
          setActiveStep(0);
          setIsOpen(false);
        }}
        onOpenChange={({ isOpen }) => {
          setIsOpen(isOpen);
        }}
        onStepChange={(step) => {
          setActiveStep(step);
        }}
      >
        <Box
          display="flex"
          flexDirection={{ base: 'column', m: 'row' }}
          gap="spacing.4"
          alignItems="stretch"
        >
          <SpotlightPopoverTourStep name="refunds-step">
            <Box width="100%">
              <Card width="100%" height="100%">
                <CardBody>
                  <Box display="flex" flexDirection="column" gap="spacing.3">
                    <Box display="flex" alignItems="center" gap="spacing.3">
                      <Text>Refunds</Text>
                      <InfoIcon color="surface.icon.gray.muted" />
                    </Box>
                    <Amount value={40000} type="heading" size="large" />
                    <Text color="surface.text.gray.muted">3 Processed</Text>
                  </Box>
                </CardBody>
              </Card>
            </Box>
          </SpotlightPopoverTourStep>

          <SpotlightPopoverTourStep name="disputes-step">
            <Box width="100%">
              <Card width="100%" height="100%">
                <CardBody>
                  <Box display="flex" flexDirection="column" gap="spacing.3">
                    <Box display="flex" alignItems="center" gap="spacing.3">
                      <Text>Disputes</Text>
                      <InfoIcon color="interactive.icon.gray.muted" />
                    </Box>
                    <Amount value={0} type="heading" size="large" />

                    <SpotlightPopoverTourStep name="status-step">
                      <Box
                        display="flex"
                        justifyContent="space-between"
                        alignItems="center"
                        gap="spacing.3"
                      >
                        <Text color="surface.text.gray.muted">0 Open | 0 Under review</Text>
                        <Button size="small" variant="tertiary">
                          Review
                        </Button>
                      </Box>
                    </SpotlightPopoverTourStep>
                  </Box>
                </CardBody>
              </Card>
            </Box>
          </SpotlightPopoverTourStep>
        </Box>
      </SpotlightPopoverTour>
    </Box>
  );
}
```

### Interruptible Tour Example

This example shows an advanced implementation of a tour that can be interrupted or skipped, with dynamic step content that changes based on whether the user completed or skipped the tour.

```jsx
import { useState } from 'react';
import {
  SpotlightPopoverTour,
  SpotlightPopoverTourStep,
  SpotlightPopoverTourFooter,
  Box,
  Button,
  Text,
  Code,
} from '@razorpay/blade/components';

function InterruptibleTourExample() {
  const [activeStep, setActiveStep] = useState(0);
  const [isTourSkipped, setIsTourSkipped] = useState(false);
  const [isOpen, setIsOpen] = useState(false);

  // Custom footer with skip functionality
  const InterruptibleTourFooter = ({
    activeStep,
    goToNext,
    goToStep,
    stopTour,
    goToPrevious,
    totalSteps,
  }) => {
    const isLast = activeStep === totalSteps - 1;
    const isFirst = activeStep === 0;

    return (
      <Box display="flex" justifyContent="space-between" alignItems="center" gap="spacing.7">
        <Text size="small" weight="semibold">
          {activeStep + 1} / {totalSteps}
        </Text>
        <Box display="flex" gap="spacing.4">
          <Button
            size="small"
            variant="tertiary"
            onClick={() => {
              setIsTourSkipped(true);
              goToStep(totalSteps - 1);
            }}
          >
            Skip Tour
          </Button>
          {!isFirst && (
            <Button
              size="small"
              variant="secondary"
              onClick={() => {
                goToPrevious();
              }}
            >
              Prev
            </Button>
          )}
          {isLast ? (
            <Button
              size="small"
              onClick={() => {
                stopTour();
              }}
            >
              Done
            </Button>
          ) : (
            <Button
              size="small"
              onClick={() => {
                goToNext();
              }}
            >
              Next
            </Button>
          )}
        </Box>
      </Box>
    );
  };

  // Define steps dynamically based on state
  const steps: SpotlightPopoverTourSteps = [
    {
      name: 'step-1',
      title: 'Step 1',
      content: () => (
        <Box>
          <Text color="surface.text.gray.subtle">This is step 1, press skip</Text>
        </Box>
      ),
      placement: 'top' as const,
      footer: (props) => <InterruptibleTourFooter {...props} />,
    },
    {
      name: 'step-2',
      title: 'Step 2',
      content: () => (
        <Box>
          <Text color="surface.text.gray.subtle">This is step 2</Text>
        </Box>
      ),
      placement: 'bottom' as const,
      footer: (props) => <InterruptibleTourFooter {...props} />,
    },
    // The final step changes based on whether user skipped or completed
    isTourSkipped
      ? {
          name: 'final-step',
          title: 'Tour Incomplete!',
          content: () => (
            <Text color="surface.text.gray.subtle">
              We recommend that you complete the tour to make the most of the new features. You can
              find it here when you want to take it.
            </Text>
          ),
          footer: ({ stopTour }) => (
            <Button
              size="small"
              onClick={() => {
                stopTour();
              }}
            >
              Got it
            </Button>
          ),
        }
      : {
          name: 'final-step',
          title: 'Tour Complete!',
          content: () => (
            <Text color="surface.text.gray.subtle">
              You have completed the tour. You can find it here when you want to take it.
            </Text>
          ),
          footer: ({ stopTour }) => (
            <Button
              size="small"
              onClick={() => {
                stopTour();
              }}
            >
              Thanks.
            </Button>
          ),
        },
  ];

  return (
    <Box>
      <SpotlightPopoverTour
        steps={steps}
        isOpen={isOpen}
        activeStep={activeStep}
        onFinish={() => {
          setIsOpen(false);
          setIsTourSkipped(false);
          setActiveStep(0);
        }}
        onOpenChange={({ isOpen }) => {
          setIsOpen(isOpen);
        }}
        onStepChange={(step) => {
          setActiveStep(step);
        }}
      >
        <SpotlightPopoverTourStep name="final-step">
          <Button
            marginBottom="spacing.5"
            onClick={() => {
              setIsOpen(!isOpen);
            }}
          >
            {isOpen ? 'Tour In Progress' : 'Start Tour'}
          </Button>
        </SpotlightPopoverTourStep>

        <Text>
          You can create complex flows like interruptible tours by dynamically modifying the steps
          array, and changing its contents.
        </Text>

        <Text>
          Compose and make use of methods provided by the tour component like{' '}
          <Code size="medium">stopTour</Code>, <Code size="medium">goToStep</Code>,{' '}
          <Code size="medium">goToNext</Code> etc to control the behavior of the current tour step
        </Text>

        <Box display="flex" gap="spacing.4" alignItems="stretch" marginTop="spacing.6">
          <SpotlightPopoverTourStep name="step-1">
            <Box padding="spacing.4" backgroundColor="surface.background.gray.intense">
              Step 1
            </Box>
          </SpotlightPopoverTourStep>

          <SpotlightPopoverTourStep name="step-2">
            <Box padding="spacing.4" backgroundColor="surface.background.gray.intense">
              Step 2
            </Box>
          </SpotlightPopoverTourStep>
        </Box>
      </SpotlightPopoverTour>
    </Box>
  );
}
```
