## 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.

```tsx
import { useState } from 'react';
import {
  SpotlightPopoverTour,
  SpotlightPopoverTourStep,
  SpotlightPopoverTourFooter,
  Box,
  Button,
  Text,
  Card,
  CardBody,
  InfoIcon,
  Amount,
} from '@razorpay/blade/components';
import type {
  SpotlightPopoverTourSteps,
  SpotlightPopoverStepRenderProps,
} from '@razorpay/blade/components';
// Custom footer component that can control the tour
const CustomTourFooter = ({
  activeStep,
  totalSteps,
  goToNext,
  goToPrevious,
  stopTour,
}: SpotlightPopoverStepRenderProps): React.ReactElement => {
  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,
            },
      }}
    />
  );
};

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

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

export default BasicTourExample;

```
### 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.

```tsx
import { useState } from 'react';
import {
  SpotlightPopoverTour,
  SpotlightPopoverTourStep,
  Box,
  Button,
  Text,
  Code,
} from '@razorpay/blade/components';
import type {
  SpotlightPopoverTourSteps,
  SpotlightPopoverStepRenderProps,
} from '@razorpay/blade/components';

const InterruptibleTourFooter = ({
  activeStep,
  goToNext,
  goToStep,
  stopTour,
  goToPrevious,
  totalSteps,
  setIsTourSkipped,
}: SpotlightPopoverStepRenderProps & {
  setIsTourSkipped: (isTourSkipped: boolean) => void;
}): React.ReactElement => {
  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>
  );
};

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

  // 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
          activeStep={props.activeStep}
          goToNext={props.goToNext}
          goToStep={props.goToStep}
          stopTour={props.stopTour}
          goToPrevious={props.goToPrevious}
          totalSteps={props.totalSteps}
          setIsTourSkipped={setIsTourSkipped}
        />
      ),
    },
    {
      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
          activeStep={props.activeStep}
          goToNext={props.goToNext}
          goToStep={props.goToStep}
          stopTour={props.stopTour}
          goToPrevious={props.goToPrevious}
          totalSteps={props.totalSteps}
          setIsTourSkipped={setIsTourSkipped}
        />
      ),
    },
    // 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>
  );
}

export default InterruptibleTourExample;

```