Skip to content

sjmc11/vue-router-newtab

Repository files navigation

New Tab Router

npm version License: MIT TypeScript

A Vue 3 + Vue Router 4 package that adds intelligent navigation behavior, specifically Cmd/Ctrl+click functionality to programmatic router.push() calls.

✨ Features

  • 🎯 Smart Navigation: Automatically detects Cmd/Ctrl key presses during router.push() calls
  • πŸ†• New Tab Support: Opens routes in new tabs when modifier keys are pressed
  • πŸ”§ Highly Configurable: Custom behaviors, callbacks, and route patterns
  • πŸ“± Cross-Platform: Works on macOS (Cmd), Windows/Linux (Ctrl)
  • πŸ›‘οΈ Type Safe: Full TypeScript support with comprehensive type definitions
  • πŸš€ Zero Breaking Changes: Non-intrusive addition of new tab functionality to existing router
  • πŸ“¦ Tree Shakeable: Optimized bundle size with ESM support
  • πŸ§ͺ Well Tested: Comprehensive test coverage with Vitest and Playwright

πŸš€ Quick Start

Installation

npm install vue-router-newtab
# or
yarn add vue-router-newtab
# or
pnpm add vue-router-newtab

Basic Usage

import { createRouter, createWebHistory } from 'vue-router';
import { newTabRouter } from 'vue-router-newtab';

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About },
    { path: '/contact', component: Contact },
  ],
});

// Enhance the router with Cmd/Ctrl+click support
newTabRouter(router);

// Now your existing router.push() calls work intelligently!
// Cmd/Ctrl + router.push('/about') = opens in new tab
// Normal router.push('/about') = normal navigation

Using with unplugin-vue-router

If you're using unplugin-vue-router for file-based routing, you need to import the type declarations in your main setup file:

// main.ts or router setup file
import 'vue-router-newtab/unplugin-vue-router.d.ts';
import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import { newTabRouter } from 'vue-router-newtab';

// Your router setup with unplugin-vue-router
const router = createRouter({
  history: createWebHistory(),
  routes: [], // Routes are auto-generated by unplugin-vue-router
});

// Enhance the router with Cmd/Ctrl+click support
newTabRouter(router);

This import ensures that TypeScript recognizes the enhanced router.push() method with the additional options when using unplugin-vue-router's typed routing.

In Your Components

<template>
  <div>
    <button @click="navigateToAbout">About (Cmd/Ctrl+click for new tab)</button>
    <button @click="forceNewTab">Force New Tab</button>
  </div>
</template>

<script setup lang="ts">
import { useRouter } from 'vue-router';

const router = useRouter();

const navigateToAbout = () => {
  // This will open in new tab if Cmd/Ctrl is pressed
  router.push('/about');
};

const forceNewTab = () => {
  // This will always open in new tab
  router.push('/about', { forceNewTab: true });
};

const conditionalNewTab = () => {
  // This will only open in new tab if Cmd/Ctrl is pressed
  router.push('/about', { newTab: true });
};
</script>

πŸ“– API Reference

newTabRouter(router, config?)

Adds new tab functionality to a Vue Router instance with intelligent navigation behavior.

Parameters:

  • router: Router - The Vue Router instance to support newTab behaviour
  • config?: NewTabRouterConfig - Optional configuration object

Returns: NewTabRouter - The router instance with new tab functionality

Configuration Options

interface NewTabRouterConfig {
  /** Enable Cmd/Ctrl+click detection (default: true) */
  enableCtrlClick?: boolean;

  /** Enable debug logging (default: false) */
  debugMode?: boolean;
}

Enhanced Push Options

interface EnhancedPushOptions {
  /** Force opening in new tab regardless of modifier key */
  forceNewTab?: boolean;

  /** Open in new tab only if modifier key is pressed (false prevents new tab behavior) */
  newTab?: boolean;
}

πŸŽ›οΈ Advanced Usage

Debug Mode

newTabRouter(router, {
  debugMode: process.env.NODE_ENV === 'development',
});

Per-Call Customization

// Force new tab for specific calls
router.push('/external-link', { forceNewTab: true });

// Conditional new tab (only if modifier key is pressed)
router.push('/optional-new-tab', { newTab: true });

// Prevent new tab behavior for specific calls
router.push('/normal-navigation', { newTab: false });

πŸ”§ TypeScript Support

The package provides comprehensive TypeScript support with full type definitions:

import type {
  NewTabRouterConfig,
  EnhancedPushOptions,
  NewTabRouter,
} from 'vue-router-newtab';

// Your router is now fully typed
const router: NewTabRouter = newTabRouter(
  createRouter({
    /* ... */
  })
);

// newTab push method with full type safety
router.push('/about', { forceNewTab: true });

πŸ§ͺ Testing

Unit Tests

npm run test

Coverage

npm run test:coverage

E2E Tests

npm run test:e2e

🌍 Browser Support

  • βœ… Chrome 88+
  • βœ… Firefox 85+
  • βœ… Safari 14+
  • βœ… Edge 88+

πŸ“¦ Bundle Size

  • ESM: ~3.2KB gzipped
  • CJS: ~3.5KB gzipped

🚨 Important Notes

SSR Compatibility

The new tab router automatically detects server-side environments and skips new tab functionality to prevent SSR errors:

// Safe to use in SSR - will be skipped automatically
newTabRouter(router);

Memory Management

The new tab router automatically cleans up event listeners when the router is destroyed. For manual cleanup:

import { destroyNewTabRouter } from 'vue-router-newtab';

// Clean up when needed
destroyNewTabRouter(router);

Security Considerations

  • New tabs are opened with noopener,noreferrer for security
  • External URLs are detected and handled appropriately
  • Popup blockers are handled gracefully with fallback to normal navigation

πŸ”„ Migration Guide

From Existing Projects

The new tab router is designed to be non-intrusive. Your existing code will work without changes:

// Before
router.push('/about');

// After (same code, enhanced behavior)
newTabRouter(router);
router.push('/about'); // Now supports Cmd/Ctrl+click!

🀝 Contributing

Contributions are welcome! Please read our Contributing Guide for details.

Development Setup

# Clone the repository
git clone https://github.com/sjmc11/vue-router-newtab.git

# Install dependencies
npm install

# Run tests
npm run test

# Build the package
npm run build

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • Vue.js team for the amazing framework
  • Vue Router team for the excellent routing solution
  • All contributors who help make this project better

πŸ“ž Support


Made with ❀️ for the Vue.js community

About

Cmd/Ctrl+click support for newTab router.push() navigation for Vue 3 + Vue Router 4

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published