npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vue-tour-kit

v1.0.1

Published

A modern, production-ready guided tour library for Vue 3

Readme

Vue Guided Tour

A modern, production-ready guided tour library for Vue 3 applications. Built with TypeScript, following SOLID principles and clean architecture patterns.

Table of Contents

  1. Installation
  2. Quick Start
  3. Core Concepts
  4. API Reference
  5. Configuration Options
  6. Tour Steps
  7. Hooks and Events
  8. Customization
  9. Theming
  10. Slots
  11. CSS Variables
  12. Keyboard Navigation
  13. Accessibility
  14. Architecture
  15. TypeScript Types

Installation

# npm
npm install vue-tour-kit

# yarn
yarn add vue-tour-kit

# pnpm
pnpm add vue-tour-kit

Import the library and its styles in your main entry file:

import { createTour } from 'vue-tour-kit'
import 'vue-tour-kit/dist/style.css'

Quick Start

Basic Example

<script setup lang="ts">
import { ref } from 'vue'
import { createTour } from 'vue-tour-kit'
import type { TourStep } from 'vue-tour-kit'
import TourRoot from 'vue-tour-kit/components/TourRoot.vue'
import 'vue-tour-kit/dist/style.css'

const tourController = ref<ReturnType<typeof createTour> | null>(null)
const showTour = ref(false)

const steps: TourStep[] = [
  {
    target: '#welcome-button',
    title: 'Welcome',
    content: 'This is your first step in the tour.',
    position: 'bottom'
  },
  {
    target: '#settings-menu',
    title: 'Settings',
    content: 'Access your application settings here.',
    position: 'left'
  },
  {
    target: '#help-section',
    title: 'Need Help?',
    content: 'Find documentation and support resources.',
    position: 'top'
  }
]

function startTour() {
  tourController.value = createTour({
    steps,
    options: {
      overlayOpacity: 0.75,
      showProgress: true,
      keyboardNavigation: true
    },
    hooks: {
      onStart: () => {
        showTour.value = true
      },
      onFinish: () => {
        showTour.value = false
      },
      onSkip: () => {
        showTour.value = false
      }
    }
  })

  tourController.value.start()
}
</script>

<template>
  <button @click="startTour">Start Tour</button>

  <TourRoot
    v-if="showTour && tourController"
    :state="tourController.state"
    :options="tourController.getOptions()"
    :current-step="tourController.getCurrentStep()"
    :position="calculatedPosition"
    :target-rect="tourController.state.targetRect"
    :can-go-next="tourController.canGoNext()"
    :can-go-prev="tourController.canGoPrev()"
    @next="tourController.next()"
    @prev="tourController.prev()"
    @close="tourController.stop()"
  />
</template>

Core Concepts

Tour Controller

The createTour function returns a controller object that manages the entire tour lifecycle. The controller provides methods for navigation, state access, and tour control.

const controller = createTour({
  steps: TourStep[],
  options?: TourOptions,
  hooks?: TourHooks
})

Controller Methods

| Method | Return Type | Description | |--------|-------------|-------------| | start() | void | Begins the tour at step 0 | | stop() | void | Ends the tour and cleans up resources | | next() | Promise<void> | Advances to the next step | | prev() | Promise<void> | Returns to the previous step | | goTo(index) | Promise<void> | Jumps to a specific step by index | | canGoNext() | boolean | Returns true if not on the last step | | canGoPrev() | boolean | Returns true if not on the first step | | getCurrentStep() | TourStep \| null | Returns the current step object | | getOptions() | RequiredTourOptions | Returns merged options with defaults | | getPositionCalculator() | PositionCalculator | Returns the positioning system instance | | destroy() | void | Cleans up all resources and listeners |

Controller State

The controller exposes a reactive state object:

interface TourState {
  isActive: boolean        // Whether the tour is currently running
  currentStep: number      // Zero-based index of current step
  totalSteps: number       // Total number of steps in the tour
  status: TourStatus       // 'idle' | 'running' | 'paused' | 'completed'
  targetElement: HTMLElement | null  // The current target DOM element
  targetRect: DOMRect | null         // Bounding rectangle of target element
}

API Reference

createTour Function

function createTour(config: {
  steps: TourStep[]
  options?: TourOptions
  hooks?: TourHooks
}): TourController

Parameters:

  • steps (required): Array of tour step definitions
  • options (optional): Configuration options for tour behavior
  • hooks (optional): Callback functions for tour events

Returns: A TourController instance with full control over the tour.


Configuration Options

TourOptions Interface

interface TourOptions {
  overlayOpacity?: number      // Default: 0.75
  zIndex?: number              // Default: 9999
  scrollBehavior?: ScrollBehavior  // Default: 'smooth'
  scrollOffset?: number        // Default: 20
  keyboardNavigation?: boolean // Default: true
  closeOnOverlayClick?: boolean // Default: true
  showProgress?: boolean       // Default: true
  debug?: boolean              // Default: false
}

Option Details

overlayOpacity

  • Type: number
  • Default: 0.75
  • Range: 0 to 1
  • Description: Opacity of the dark overlay that covers the page. A value of 0 makes it fully transparent, 1 makes it fully opaque.

zIndex

  • Type: number
  • Default: 9999
  • Description: The z-index of the tour elements. Should be higher than any other elements in your application.

scrollBehavior

  • Type: 'smooth' | 'instant' | 'auto'
  • Default: 'smooth'
  • Description: How the page scrolls when moving to a step target that is outside the viewport.

scrollOffset

  • Type: number
  • Default: 20
  • Description: Extra pixels of padding when scrolling an element into view.

keyboardNavigation

  • Type: boolean
  • Default: true
  • Description: Enables keyboard controls. Arrow keys navigate between steps, Escape closes the tour.

closeOnOverlayClick

  • Type: boolean
  • Default: true
  • Description: Whether clicking on the overlay (outside the tooltip) closes the tour.

showProgress

  • Type: boolean
  • Default: true
  • Description: Shows a progress indicator (dots, bar, or text) in the tooltip footer.

debug

  • Type: boolean
  • Default: false
  • Description: Enables debug logging to the console.

Tour Steps

TourStep Interface

interface TourStep {
  target: string | HTMLElement | (() => HTMLElement)
  title?: string
  content: string
  position?: Position
  highlightPadding?: number
  disableInteraction?: boolean
  beforeEnter?: () => void | Promise<void>
  afterLeave?: () => void | Promise<void>
}

Step Properties

target (required)

  • Type: string | HTMLElement | (() => HTMLElement)
  • Description: The element to highlight. Can be:
    • A CSS selector string (e.g., '#my-button', '.sidebar-menu')
    • A direct HTMLElement reference
    • A function that returns an HTMLElement (useful for dynamically rendered elements)

title (optional)

  • Type: string
  • Description: The heading displayed in the tooltip.

content (required)

  • Type: string
  • Description: The main text content of the tooltip.

position (optional)

  • Type: 'top' | 'bottom' | 'left' | 'right' | 'auto'
  • Default: 'auto'
  • Description: Preferred position of the tooltip relative to the target element. When set to 'auto', the system calculates the best position based on available viewport space.

highlightPadding (optional)

  • Type: number
  • Default: 8
  • Description: Extra padding around the highlighted element in pixels.

disableInteraction (optional)

  • Type: boolean
  • Default: false
  • Description: When true, prevents user interaction with the target element during this step.

beforeEnter (optional)

  • Type: () => void | Promise<void>
  • Description: Callback executed before entering this step. Can be async. Useful for preparing the UI (opening menus, loading data).

afterLeave (optional)

  • Type: () => void | Promise<void>
  • Description: Callback executed after leaving this step. Can be async. Useful for cleanup operations.

Step Examples

const steps: TourStep[] = [
  // Basic step with selector
  {
    target: '#submit-button',
    title: 'Submit Form',
    content: 'Click here to submit your changes.',
    position: 'top'
  },

  // Step with async preparation
  {
    target: '#dropdown-menu',
    title: 'Menu Options',
    content: 'Access additional features from this menu.',
    position: 'bottom',
    beforeEnter: async () => {
      // Open the dropdown before showing the step
      document.getElementById('dropdown-trigger')?.click()
      await new Promise(resolve => setTimeout(resolve, 300))
    },
    afterLeave: () => {
      // Close the dropdown after leaving
      document.getElementById('dropdown-trigger')?.click()
    }
  },

  // Step with function target for dynamic elements
  {
    target: () => document.querySelector('.dynamic-element') as HTMLElement,
    title: 'Dynamic Content',
    content: 'This element is rendered dynamically.',
    position: 'auto'
  },

  // Step with increased highlight padding
  {
    target: '#small-icon',
    title: 'Small Element',
    content: 'This small icon has extra highlight padding for visibility.',
    highlightPadding: 16
  }
]

Hooks and Events

TourHooks Interface

interface TourHooks {
  onStart?: () => void
  onFinish?: () => void
  onStepChange?: (step: TourStep, index: number) => void
  onSkip?: () => void
}

Hook Descriptions

onStart

  • Triggered: When controller.start() is called
  • Use case: Initialize UI state, show tour container, track analytics

onFinish

  • Triggered: When the tour completes normally (user clicks Finish on last step)
  • Use case: Clean up UI, save completion status, show success message

onStepChange

  • Triggered: After each step transition (including the first step)
  • Parameters: Current step object and its zero-based index
  • Use case: Track progress, update external UI, log analytics

onSkip

  • Triggered: When user closes the tour before completion (overlay click, Escape key, close button)
  • Use case: Track abandonment, save partial progress, show alternative help

Hook Examples

const tour = createTour({
  steps,
  hooks: {
    onStart: () => {
      console.log('Tour started')
      analytics.track('tour_started')
    },

    onFinish: () => {
      console.log('Tour completed')
      localStorage.setItem('tourCompleted', 'true')
      analytics.track('tour_completed')
    },

    onStepChange: (step, index) => {
      console.log(`Now on step ${index + 1}: ${step.title}`)
      analytics.track('tour_step_viewed', { step: index, title: step.title })
    },

    onSkip: () => {
      console.log('Tour skipped')
      analytics.track('tour_skipped')
    }
  }
})

Customization

TourTooltip Props

The TourTooltip component accepts these customization props:

interface TooltipProps {
  step: TourStep
  position: PositionResult
  currentIndex: number
  totalSteps: number
  showProgress: boolean
  canGoNext: boolean
  canGoPrev: boolean
  zIndex: number
  theme?: 'default' | 'dark' | 'minimal' | 'colorful'
  showCloseButton?: boolean
  showArrow?: boolean
  prevLabel?: string
  nextLabel?: string
  finishLabel?: string
  progressVariant?: 'dots' | 'bar' | 'text'
}

Customization Options

theme

  • Type: 'default' | 'dark' | 'minimal' | 'colorful'
  • Default: 'default'
  • Description: Predefined visual theme for the tooltip

showCloseButton

  • Type: boolean
  • Default: true
  • Description: Whether to show the X close button in the header

showArrow

  • Type: boolean
  • Default: true
  • Description: Whether to show the arrow pointing to the target element

prevLabel

  • Type: string
  • Default: 'Previous'
  • Description: Text for the Previous button

nextLabel

  • Type: string
  • Default: 'Next'
  • Description: Text for the Next button

finishLabel

  • Type: string
  • Default: 'Finish'
  • Description: Text for the Finish button (shown on last step)

progressVariant

  • Type: 'dots' | 'bar' | 'text'
  • Default: 'dots'
  • Description: Style of the progress indicator

Theming

Available Themes

default

Light theme with white background, blue accent colors.

dark

Dark theme with dark gray background, light text.

minimal

Subtle theme with reduced shadows and border styling.

colorful

Gradient background with purple-blue colors.

Using Themes

<TourTooltip
  :step="currentStep"
  :position="position"
  theme="dark"
  ...
/>

Theme CSS Variables

Each theme sets these CSS custom properties:

--tour-tooltip-bg           /* Tooltip background color */
--tour-title-color          /* Title text color */
--tour-content-color        /* Content text color */
--tour-close-color          /* Close button color */
--tour-close-hover-bg       /* Close button hover background */
--tour-btn-primary-bg       /* Primary button background */
--tour-btn-primary-color    /* Primary button text color */
--tour-btn-primary-hover-bg /* Primary button hover background */
--tour-btn-secondary-bg     /* Secondary button background */
--tour-btn-secondary-color  /* Secondary button text color */
--tour-btn-secondary-hover-bg /* Secondary button hover background */
--tour-progress-dot-bg      /* Inactive progress dot color */
--tour-progress-dot-active  /* Active progress dot color */
--tour-border-color         /* Border color for dividers */

Slots

The TourTooltip component provides slots for complete customization.

Available Slots

default

Complete control over entire tooltip content.

<TourTooltip ...>
  <template #default="{ step, index }">
    <div class="my-custom-tooltip">
      <h1>{{ step.title }}</h1>
      <p>{{ step.content }}</p>
      <span>Step {{ index + 1 }}</span>
    </div>
  </template>
</TourTooltip>

header

Customize the header section (title and close button).

<TourTooltip ...>
  <template #header="{ step, index, close }">
    <div class="custom-header">
      <span class="step-badge">{{ index + 1 }}</span>
      <h3>{{ step.title }}</h3>
      <button @click="close">X</button>
    </div>
  </template>
</TourTooltip>

content

Customize the main content area.

<TourTooltip ...>
  <template #content="{ step, index }">
    <div class="custom-content" v-html="step.content"></div>
  </template>
</TourTooltip>

footer

Customize the entire footer (progress and actions).

<TourTooltip ...>
  <template #footer="{ step, index, canGoNext, canGoPrev, next, prev, close }">
    <div class="custom-footer">
      <button v-if="canGoPrev" @click="prev">Back</button>
      <button v-if="canGoNext" @click="next">Continue</button>
      <button v-else @click="close">Done</button>
    </div>
  </template>
</TourTooltip>

progress

Customize only the progress indicator.

<TourTooltip ...>
  <template #progress="{ current, total }">
    <div class="custom-progress">
      {{ current + 1 }} of {{ total }}
    </div>
  </template>
</TourTooltip>

actions

Customize only the navigation buttons.

<TourTooltip ...>
  <template #actions="{ canGoNext, canGoPrev, next, prev, close }">
    <div class="custom-actions">
      <button v-if="canGoPrev" @click="prev">Previous</button>
      <button v-if="canGoNext" @click="next">Next</button>
      <button v-else @click="close">Finish</button>
    </div>
  </template>
</TourTooltip>

Slot Props Reference

| Slot | Props | |------|-------| | default | { step: TourStep, index: number } | | header | { step: TourStep, index: number, close: () => void } | | content | { step: TourStep, index: number } | | footer | { step: TourStep, index: number, canGoNext: boolean, canGoPrev: boolean, next: () => void, prev: () => void, close: () => void } | | progress | { current: number, total: number } | | actions | { canGoNext: boolean, canGoPrev: boolean, next: () => void, prev: () => void, close: () => void } |


CSS Variables

Animation Variables

:root {
  --tour-animation-duration: 300ms;
  --tour-animation-easing: ease-out;
}

Tooltip Variables

:root {
  --tour-tooltip-bg: #ffffff;
  --tour-tooltip-radius: 8px;
  --tour-tooltip-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  --tour-tooltip-max-width: 340px;
  --tour-font-family: system-ui, -apple-system, sans-serif;
}

Color Variables

:root {
  --tour-title-color: #111827;
  --tour-content-color: #4b5563;
  --tour-close-color: #6b7280;
  --tour-close-hover-bg: #f3f4f6;
  --tour-close-hover-color: #111827;
  --tour-highlight-color: #3b82f6;
  --tour-focus-color: #3b82f6;
  --tour-hint-color: #9ca3af;
  --tour-border-color: #e5e7eb;
}

Button Variables

:root {
  --tour-btn-primary-bg: #3b82f6;
  --tour-btn-primary-color: #ffffff;
  --tour-btn-primary-hover-bg: #2563eb;
  --tour-btn-secondary-bg: #f3f4f6;
  --tour-btn-secondary-color: #374151;
  --tour-btn-secondary-hover-bg: #e5e7eb;
}

Progress Variables

:root {
  --tour-progress-dot-bg: #e5e7eb;
  --tour-progress-dot-active: #3b82f6;
  --tour-progress-bar-bg: #e5e7eb;
  --tour-progress-bar-fill: #3b82f6;
}

Customizing with CSS Variables

/* Custom theme example */
.my-app {
  --tour-tooltip-bg: #1a1a2e;
  --tour-title-color: #eaeaea;
  --tour-content-color: #a0a0a0;
  --tour-btn-primary-bg: #e94560;
  --tour-highlight-color: #e94560;
  --tour-animation-duration: 400ms;
}

Keyboard Navigation

When keyboardNavigation is enabled (default):

| Key | Action | |-----|--------| | Right Arrow | Go to next step | | Left Arrow | Go to previous step | | Escape | Close the tour | | Enter or Space | Go to next step or finish if on last step |


Accessibility

ARIA Attributes

The tooltip uses proper ARIA attributes:

  • role="dialog" on the tooltip container
  • aria-modal="true" to indicate modal behavior
  • aria-label for close and navigation buttons
  • aria-hidden="true" on decorative elements (arrow, SVG icons)

Focus Management

  • Focus is trapped within the tooltip when active
  • Previous focus is restored when the tour ends
  • Tab key cycles through interactive elements within the tooltip

Screen Reader Support

  • Step titles are announced via heading elements
  • Progress is communicated via text alternatives
  • Button labels clearly describe their actions

Architecture

Component Hierarchy

TourRoot
  TourOverlay (dark backdrop with spotlight cutout)
  TourHighlight (pulsing border around target)
  TourTooltip (content bubble with navigation)
    TourProgress (step indicator)

Module Structure

src/
  core/
    createTour.ts      # Factory function
    TourController.ts  # Main orchestrator
    TourState.ts       # Reactive state management
    TourNavigator.ts   # Step navigation logic
    TourEventBus.ts    # Event pub/sub system
    KeyboardHandler.ts # Keyboard controls
    types.ts           # TypeScript definitions

  dom/
    DomResolver.ts     # Element resolution with retries
    ScrollManager.ts   # Scroll-into-view handling
    FocusManager.ts    # Focus trap management

  positioning/
    PositionCalculator.ts   # Main positioning logic
    CollisionDetector.ts    # Viewport boundary detection
    strategies/
      TopStrategy.ts
      BottomStrategy.ts
      LeftStrategy.ts
      RightStrategy.ts
      AutoStrategy.ts       # Smart auto-positioning

  renderer/
    components/
      TourRoot.vue
      TourOverlay.vue
      TourTooltip.vue
      TourHighlight.vue
      TourProgress.vue

  composables/
    useTour.ts          # Main tour control composable
    useTourStep.ts      # Dynamic step registration
    useTourState.ts     # State access composable

Positioning System

The positioning system uses a strategy pattern:

  1. Calculate preferred position based on step configuration
  2. Check for viewport collisions
  3. If collision detected and position is not 'auto', try auto-positioning
  4. Auto-positioning evaluates available space in all directions
  5. Choose position with most available space
  6. Calculate arrow position for visual connection to target

TypeScript Types

Core Types

type Position = 'top' | 'bottom' | 'left' | 'right' | 'auto'

type ScrollBehavior = 'smooth' | 'instant' | 'auto'

type TourStatus = 'idle' | 'running' | 'paused' | 'completed'

type ArrowSide = 'top' | 'bottom' | 'left' | 'right'

Step and Options Types

interface TourStep {
  target: string | HTMLElement | (() => HTMLElement)
  title?: string
  content: string
  position?: Position
  highlightPadding?: number
  disableInteraction?: boolean
  beforeEnter?: () => void | Promise<void>
  afterLeave?: () => void | Promise<void>
}

interface TourOptions {
  overlayOpacity?: number
  zIndex?: number
  scrollBehavior?: ScrollBehavior
  scrollOffset?: number
  keyboardNavigation?: boolean
  closeOnOverlayClick?: boolean
  showProgress?: boolean
  debug?: boolean
}

State and Position Types

interface TourState {
  isActive: boolean
  currentStep: number
  totalSteps: number
  status: TourStatus
  targetElement: HTMLElement | null
  targetRect: DOMRect | null
}

interface PositionResult {
  top: number
  left: number
  arrowPosition: {
    side: ArrowSide
    offset: number
  }
}

Event Types

type TourEventType =
  | 'tour:start'
  | 'tour:stop'
  | 'tour:complete'
  | 'tour:step-change'
  | 'tour:step-enter'
  | 'tour:step-leave'
  | 'tour:error'

interface TourEventPayloads {
  'tour:start': undefined
  'tour:stop': undefined
  'tour:complete': undefined
  'tour:step-change': { step: TourStep; index: number }
  'tour:step-enter': { step: TourStep; index: number }
  'tour:step-leave': { step: TourStep; index: number }
  'tour:error': { error: Error; context?: string }
}

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

Requires Vue 3.3.0 or higher.


License

MIT License