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

v-tour-guide

v1.2.1

Published

A comprehensive Vue 3 tour guide library with TypeScript support for Vue and Nuxt applications

Readme

Vue Tour Guide

A comprehensive Vue 3 tour guide library with TypeScript support for Vue and Nuxt applications.

Features

  • 🎯 Precise Element Targeting - Target elements using CSS selectors or data attributes
  • 🎨 Beautiful Tooltips - Customizable tooltips with multiple directions and styling options
  • 📱 Responsive Design - Works seamlessly across all device sizes
  • 🔄 Real-time Position Tracking - Automatic position updates during scrolling and resizing
  • Performance Optimized - Efficient rendering with 60fps position monitoring
  • 🎪 Flexible Positioning - Support for separate tooltip targeting and custom offsets
  • 🔧 TypeScript Support - Full type safety with comprehensive interfaces
  • 🎭 Lifecycle Hooks - beforeShow, afterShow, beforeHide hooks for custom logic
  • 🌐 Framework Agnostic - Works with Vue 3 and Nuxt 3
  • Accessibility Ready - Built with screen readers and keyboard navigation in mind

Installation

npm install v-tour-guide

CSS Import

Important: You need to import the tour guide CSS for proper styling (arrows, animations, etc.):

The stylesheet is fully self-contained — it loads nothing from a CDN, requires no CSS framework, and adds no global resets to your page. It works the same whether your app uses Tailwind, Bootstrap, or plain CSS.

Option 1: Import in your plugin (Recommended)

// plugins/v-tour-guide.client.ts
import { TourGuideManager, TourGuideTooltip } from "v-tour-guide";
import "v-tour-guide/style.css"; // Add this line

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.component("TourGuideManager", TourGuideManager);
  nuxtApp.vueApp.component("TourGuideTooltip", TourGuideTooltip);
});

Option 2: Import in your component

<script setup lang="ts">
import { useTourGuide, type TourGuideStep } from "v-tour-guide";
import "v-tour-guide/style.css"; // Add this line
</script>

Option 3: Add to Nuxt config

// nuxt.config.ts
export default defineNuxtConfig({
  css: ["v-tour-guide/style.css"],
  // ... rest of your config
});

Live Demo

🎮 Try it out: Live Demo

Quick Start

Vue 3 Application

<template>
  <div>
    <!-- Your app content -->
    <div data-tour-guide="welcome">Welcome to our app!</div>
    <button data-tour-guide="action-button">Get Started</button>

    <!-- Tour Guide Manager -->
    <TourGuideManager
      :steps="tourSteps"
      :auto-start="true"
      @complete="onTourComplete"
    />
  </div>
</template>

<script setup lang="ts">
import { TourGuideManager, type TourGuideStep } from "v-tour-guide";

const tourSteps: TourGuideStep[] = [
  {
    id: "welcome",
    title: "Welcome!",
    content: "This is your first step in the tour.",
    target: "welcome",
    direction: "bottom",
    showAction: true,
  },
  {
    id: "action",
    title: "Take Action",
    content: "Click this button to get started.",
    target: "action-button",
    direction: "top",
    showAction: true,
  },
];

const onTourComplete = () => {
  // Tour completed
};
</script>

Nuxt 3 Application

  1. Create a plugin file plugins/v-tour-guide.client.ts:
import { TourGuideManager, TourGuideTooltip } from "v-tour-guide";

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.component("TourGuideManager", TourGuideManager);
  nuxtApp.vueApp.component("TourGuideTooltip", TourGuideTooltip);
});
  1. Use in your pages:
<template>
  <div>
    <div data-tour-guide="content">Your content here</div>
    <TourGuideManager :steps="steps" />
  </div>
</template>

<script setup lang="ts">
import { useTourGuide, type TourGuideStep } from "v-tour-guide";

const { startTourGuide } = useTourGuide();

const steps: TourGuideStep[] = [
  // Your tour steps
];
</script>

API Reference

TourGuideManager Component

Props

| Prop | Type | Default | Description | | ------------------- | ----------------- | ----------- | ----------------------------------------------------------------- | | steps | TourGuideStep[] | [] | Array of tour steps | | autoStart | boolean | false | Auto-start tour when component mounts | | showOverlay | boolean | true | Show dimming overlay | | allowSkip | boolean | true | Allow users to skip the tour | | allowHtml | boolean | false | Render step content as HTML (see Rich content) | | highlightPadding | number | 4 | Padding around highlighted elements (px) | | labels | TourGuideLabels | undefined | Global button labels | | allowInteractions | boolean | false | Allow interactions with other elements during tour | | scrollToView | boolean | true | Auto-scroll the target into view before highlighting | | trackAnimations | boolean | false | Poll target position each frame to follow CSS animations (see note) | | fluid | boolean | false | Ease the highlight/tooltip between steps (matched to scroll); off = instant jump | | fluidDuration | number | 300 | Fluid transition duration in ms (higher = slower); only used when fluid is on |

trackAnimations re-measures the target every animation frame. Scrolling, resizing, and DOM changes are tracked without it — only enable it if your target element moves under a CSS animation or transition while a step is showing, since it forces a layout on every frame.

Events

| Event | Payload | Description | | ------------- | -------------------------------------- | --------------------------- | | start | void | Tour has started | | complete | void | Tour completed successfully | | skip | void | Tour was skipped | | step-change | (step: TourGuideStep, index: number) | Current step changed |

Exposed Methods

// Start the tour programmatically
tourManager.startTourGuide();

// Skip/stop the tour
tourManager.skipTourGuide();

// Complete the tour
tourManager.completeTourGuide();

// Navigate to specific step
tourManager.goToStep(stepIndex);

// Navigation
tourManager.nextStep();
tourManager.previousStep();

// State access
tourManager.isActive; // readonly ref
tourManager.currentStepIndex; // readonly ref

TourGuideStep Interface

interface TourGuideStep {
  id: string; // Unique step identifier
  title: string; // Tooltip title
  content?: string; // Tooltip content
  allowHtml?: boolean; // Render content as HTML (overrides the manager prop)
  target: string; // CSS selector, class, id, or data attribute
  tooltipTarget?: string; // Separate element for tooltip positioning
  direction?: "top" | "bottom" | "left" | "right"; // Tooltip direction
  offsetX?: number; // Horizontal offset (px)
  offsetY?: number; // Vertical offset (px)
  radius?: number; // Highlight border radius (px)
  scrollToView?: boolean; // Auto-scroll to element
  showAction?: boolean; // Show action buttons
  skipLabel?: string; // Custom skip button label
  nextLabel?: string; // Custom next button label
  prevLabel?: string; // Custom previous button label
  finishLabel?: string; // Custom finish button label
  tooltip?: {
    // Tooltip customization options
    backgroundColor?: string;
    textColor?: string;
    borderRadius?: string;
    padding?: string;
    maxWidth?: string;
    minWidth?: string;
    boxShadow?: string;
    buttonBackgroundColor?: string;
    buttonTextColor?: string;
    buttonHoverColor?: string;
    skipButtonColor?: string;
    skipButtonHoverColor?: string;
    progressActiveColor?: string;
    progressInactiveColor?: string;
    tooltipClass?: string;
    headerClass?: string;
    contentClass?: string;
    actionsClass?: string;
  };
  beforeShow?: () => void | Promise<void>; // Pre-show hook
  afterShow?: () => void; // Post-show hook
  beforeHide?: () => void | Promise<void>; // Pre-hide hook
}

TourGuideLabels Interface

interface TourGuideLabels {
  skip?: string; // Label for skip button (default: "Skip")
  next?: string; // Label for next button (default: "Next")
  previous?: string; // Label for previous button (default: "Previous")
  finish?: string; // Label for finish button (default: "Finish")
}

useTourGuide Composable

const {
  tourGuideState, // Reactive state object
  startTourGuide, // Start tour function
  completeStep, // Complete specific step
  finishTourGuide, // Finish/skip tour
  resetTourGuide, // Reset tour state
  isStepCompleted, // Check if step is completed
} = useTourGuide();

Element Targeting

The target property accepts CSS selectors and data attributes:

<!-- Using data attributes (recommended) -->
<div data-tour-guide="welcome">Welcome!</div>

<!-- Using CSS selectors -->
<div id="submit-button">Submit</div>
<div class="feature-list">Features</div>
const tourSteps = [
  {
    id: "welcome",
    title: "Welcome!",
    target: "welcome", // data-tour-guide="welcome"
    content: "Welcome to our app",
  },
  {
    id: "submit",
    title: "Submit",
    target: "#submit-button", // ID selector
    content: "Click to submit",
  },
  {
    id: "features",
    title: "Features",
    target: ".feature-list", // Class selector
    content: "Check out our features",
  },
];

Tooltip Customization

You can customize tooltip appearance and behavior:

{
  id: 'custom-step',
  title: 'Custom Styled Tooltip',
  content: 'This tooltip has custom styling!',
  target: 'my-element',
  showAction: true,

  tooltip: {
    backgroundColor: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
    textColor: '#ffffff',
    borderRadius: '1rem',
    padding: '1.5rem',
    maxWidth: '24rem',
    boxShadow: '0 25px 50px -12px rgb(0 0 0 / 0.25)',
    buttonBackgroundColor: '#3b82f6',
    buttonTextColor: '#ffffff',
    buttonHoverColor: '#2563eb'
  }
}

Rich content

By default content renders as plain text, so any markup you write is escaped. There are three ways to get formatting.

1. Line breaks — no configuration needed. Newlines in a content string are preserved:

{
  id: 'welcome',
  title: 'Welcome',
  target: 'welcome-card',
  content: 'First line.\nSecond line.'
}

2. HTML — opt in with allowHtml. Set it globally on the manager, or per step to override:

<TourGuideManager :steps="steps" allow-html />
{
  id: 'welcome',
  title: 'Welcome',
  target: 'welcome-card',
  allowHtml: true,
  content: 'Press <kbd>Cmd</kbd>+<kbd>K</kbd> to open <strong>search</strong>.'
}

Security: allowHtml renders the string as-is and does not sanitize it. Only enable it for content you author. If step content can come from user input, an API, or a CMS, sanitize it yourself first (e.g. with DOMPurify) or use the content slot below instead.

3. Slots — for anything interactive. Use these when you need components, links with handlers, or images rather than a markup string.

Slots

All slots are declared on TourGuideManager and forwarded to the tooltip.

| Slot | Scope | Replaces | | ------------- | ------------------------------------------------------------------------------------------------------- | ------------------------- | | content | content, step, stepIndex, currentStep, totalSteps | The tooltip body | | header | title, step, stepIndex, currentStep, totalSteps | The title row | | skip-button | skipLabel, onSkip, step, currentStep, totalSteps | The skip button | | progress | step, stepIndex, currentStep, totalSteps | The progress dots | | actions | showPrevious, isLastStep, prevLabel, nextLabel, finishLabel, onNext, onPrevious, onSkip | The previous/next buttons |

<TourGuideManager :steps="steps">
  <template #content="{ step }">
    <p class="mb-2">{{ step.content }}</p>
    <a :href="step.docsUrl" class="underline">Read the docs</a>
  </template>

  <template #actions="{ isLastStep, onNext, onPrevious, showPrevious }">
    <button v-if="showPrevious" @click="onPrevious">Back</button>
    <button @click="onNext">{{ isLastStep ? 'Done' : 'Continue' }}</button>
  </template>
</TourGuideManager>

The content slot takes precedence over both allowHtml and the plain content string.

Advanced Features

Separate Tooltip Positioning

Highlight one element while positioning the tooltip relative to a different element:

{
  id: 'complex-step',
  title: 'Advanced Feature',
  content: 'This highlights one element but positions tooltip elsewhere.',
  target: '.main-button',        // Element to highlight
  tooltipTarget: '.tooltip-anchor', // Different element for tooltip positioning
  direction: 'right',
  showAction: true
}

Lifecycle Hooks

{
  id: 'async-step',
  title: 'Loading Data',
  target: 'data-section',
  async beforeShow() {
    await fetchData()
  },
  afterShow() {
    analytics.track('tour_step_viewed', { step: 'data-section' })
  }
}

Auto-scroll Configuration

{
  id: 'scroll-step',
  title: 'Scroll to View',
  target: 'footer-content',
  scrollToView: true, // Automatically scrolls element into view
  direction: 'top'
}

Accessibility

The tour guide is built with accessibility in mind:

  • Keyboard Navigation: Full keyboard support for navigation
  • Screen Reader Support: Proper ARIA labels and announcements
  • Focus Management: Automatic focus handling
  • High Contrast Mode: Support for high contrast themes
  • Reduced Motion: Respects prefers-reduced-motion settings

Examples

Check out the examples/ directory for detailed usage examples:

License

MIT License - see LICENSE file for details.

Support


Made with ❤️ for the Vue.js community

Trigger deployment