# Tour

Creates guided tours of a user interface.

## Import

```tsx
import { Tour, TourStep } from '@coinbase/cds-web/tour'
```

## Examples

### Basic usage

```jsx live
function Example() {
  const [activeTourStep, setActiveTourStep] = useState(null);

  const StepOne = () => {
    const [checked, setChecked] = useState(false);

    const { goNextTourStep, stopTour } = useTourContext();

    return (
      <Coachmark
        action={
          <Button compact onClick={goNextTourStep}>
            Next
          </Button>
        }
        checkbox={
          <Checkbox checked={checked} onChange={setChecked}>
            Don&apos;t show again
          </Checkbox>
        }
        content="Add up to 3 lines of body copy. Deliver your message with clarity and impact"
        onClose={stopTour}
        title="My first step"
      />
    );
  };

  const StepTwo = () => {
    const { goNextTourStep, goPreviousTourStep, stopTour } = useTourContext();
    return (
      <Coachmark
        action={
          <HStack gap={1}>
            <Button compact onClick={goPreviousTourStep} variant="secondary">
              Back
            </Button>
            <Button compact onClick={goNextTourStep}>
              Next
            </Button>
          </HStack>
        }
        content={
          <VStack gap={2}>
            <TextCaption as="p" color="fgMuted">
              50%
            </TextCaption>
            <ProgressBar progress={0.5} />
            <TextBody as="p">
              Add up to 3 lines of body copy. Deliver your message with clarity and impact
            </TextBody>
          </VStack>
        }
        media={<RemoteImage height={150} source={ethBackground} width="100%" />}
        onClose={stopTour}
        title="My second step"
      />
    );
  };

  const StepThree = () => {
    const { stopTour, goNextTourStep, goPreviousTourStep } = useTourContext();
    return (
      <Coachmark
        action={
          <HStack gap={1}>
            <Button compact onClick={goPreviousTourStep} variant="secondary">
              Back
            </Button>
            <Button compact onClick={stopTour}>
              Done
            </Button>
          </HStack>
        }
        content="Add up to 3 lines of body copy. Deliver your message with clarity and impact"
        title="My third step"
        width={350}
      />
    );
  };

  const tourSteps = [
    {
      id: 'step1',
      onBeforeActive: () => console.log('step1 before'),
      Component: StepOne,
    },
    {
      id: 'step2',
      onBeforeActive: () => console.log('step2 before'),
      Component: StepTwo,
    },
    {
      id: 'step3',
      onBeforeActive: () => console.log('step3 before'),
      Component: StepThree,
    },
  ];

  const TourExample = ({ spacerWidthIncrement = 0, spacerHeightIncrement = 500 }) => {
    const { startTour } = useTourContext();

    const handleClick = useCallback(() => startTour(), [startTour]);

    return (
      <VStack flexGrow={1} gap={2} justifyContent="space-between">
        <Button compact onClick={handleClick}>
          Start tour
        </Button>
        <TourStep id="step1">
          <Box background="bgAlternate" padding={4}>
            <TextBody as="p">This is step 1</TextBody>
          </Box>
        </TourStep>
        <Box height={spacerHeightIncrement} />
        <HStack justifyContent="flex-end">
          <Box flexShrink={0} width={spacerWidthIncrement} />
          <TourStep id="step2">
            <Box background="bgAlternate" padding={4} width={150}>
              <TextBody as="p">This is step 2</TextBody>
            </Box>
          </TourStep>
        </HStack>
        <Box height={spacerHeightIncrement} />
        <HStack>
          <Box flexShrink={0} width={spacerWidthIncrement * 2} />
          <TourStep id="step3">
            <VStack background="bgAlternate" padding={4} width={150}>
              <TextBody as="p">This is step 3</TextBody>
            </VStack>
          </TourStep>
        </HStack>
      </VStack>
    );
  };

  return (
    <Tour activeTourStep={activeTourStep} onChange={setActiveTourStep} steps={tourSteps}>
      <TourExample />
    </Tour>
  );
}
```

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `activeTourStep` | `TourStepValue<T> \| null` | Yes | `-` | - |
| `onChange` | `(tourStep: TourStepValue<T> \| null) => void` | Yes | `-` | - |
| `steps` | `TourStepValue<T>[]` | Yes | `-` | - |
| `TourMaskComponent` | `TourMaskComponent` | No | `DefaultTourMask` | The Component to render as a tour overlay and mask. |
| `TourStepArrowComponent` | `TourStepArrowComponent` | No | `DefaultTourStepArrow` | The default Component to render for each TourStep arrow element. |
| `disableAutoScroll` | `boolean` | No | `-` | Disable automatically scrolling to active elements. |
| `disablePortal` | `boolean` | No | `-` | - |
| `hideOverlay` | `boolean` | No | `false` | Hide overlay when tour is active |
| `scrollOptions` | `TourScrollOptions` | No | `{   behavior: 'smooth',   marginX: 100,   marginY: 100, }` | Controls the scrolling behavior and margins when calling element.scrollTo() to scroll to an active TourStep target. |
| `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |
| `tourMaskBorderRadius` | `string \| number` | No | `-` | Corner radius for the TourMasks content mask. Uses SVG rect elements rx and ry attributes https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx. |
| `tourMaskPadding` | `string \| number` | No | `-` | Padding to add around the edges of the TourMasks content mask. |
| `tourStepAutoPlacement` | `{ padding?: Padding; rootBoundary?: RootBoundary \| undefined; elementContext?: ElementContext \| undefined; altBoundary?: boolean \| undefined; crossAxis?: boolean \| undefined; alignment?: Alignment \| null \| undefined; autoAlignment?: boolean \| undefined; allowedPlacements?: Placement[] \| undefined; boundary?: Boundary \| undefined; } \| undefined` | No | `24` | Configures @floating-ui autoPlacement options for Tour Step component. See https://floating-ui.com/docs/autoplacement. |
| `tourStepOffset` | `number \| Partial<{ mainAxis: number; crossAxis: number; alignmentAxis: number \| null; }> \| Derivable<OffsetValue>` | No | `24` | Configures @floating-ui offset options for Tour Step component. See https://floating-ui.com/docs/offset. |
| `tourStepShift` | `{ padding?: Padding; rootBoundary?: RootBoundary \| undefined; elementContext?: ElementContext \| undefined; altBoundary?: boolean \| undefined; crossAxis?: boolean \| undefined; mainAxis?: boolean \| undefined; limiter?: { fn: (state: MiddlewareState) => Coords; options?: any; } \| undefined; boundary?: Boundary \| undefined; } \| undefined` | No | `-` | Configures @floating-ui shift options for Tour Step component. See https://floating-ui.com/docs/shift. |


