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-modaller

v1.0.11

Published

A flexible and powerful modal system for Vue 3 applications with TypeScript support, featuring draggable modals, side panels, and smooth animations

Readme

VueModaller 🎭

A flexible and powerful modal system for Vue 3 applications with TypeScript support. Create beautiful modals with draggable functionality, side panels, and smooth animations.

Version License Vue TypeScript

✨ Features

🎯 Multiple Modal Types

  • Standard Modal - Classic centered modals
  • Side Panel - Slide-in panels from the side
  • Panel Modal - Bottom-aligned panels with rounded top corners
  • Draggable Modal - Instagram-style draggable bottom sheets

📱 Responsive Design

  • Device Detection - Automatic mobile/desktop detection
  • Adaptive Types - Different modal types for mobile vs desktop
  • Touch Gestures - Smooth drag and swipe interactions
  • Velocity-based - Smart animations based on gesture speed

🎨 Highly Customizable

  • CSS Variables - Easy theming with CSS custom properties
  • BEM Methodology - Clean, maintainable CSS architecture
  • Custom Animations - Smooth CSS and JavaScript animations
  • Handle Styling - Fully customizable drag handles

🚀 Developer Experience

  • TypeScript - Full TypeScript support with detailed types
  • Vue 3 - Built for Vue 3 Composition API
  • Easy Integration - Simple composable-based API
  • Global Components - Auto-registered components
  • Slot Support - Dynamic slot content with props

📦 Installation

npm install vue-modaller
yarn add vue-modaller
pnpm add vue-modaller

🚀 Quick Start

1. Install the Plugin

import { createApp } from 'vue'
import VueModaller from 'vue-modaller'
import 'vue-modaller/dist/style.css' // Import styles
import App from './App.vue'

const app = createApp(App)
app.use(VueModaller)
app.mount('#app')

2. Add ModalRoot to Your App

<template>
  <div id="app">
    <!-- Your app content -->
    <ModalRoot />
  </div>
</template>

3. Create Your First Modal

<script setup lang="ts">
import { useModal } from 'vue-modaller'
import MyModalContent from './MyModalContent.vue'

const openStandardModal = async () => {
  const result = await useModal(MyModalContent, {
    title: 'Welcome!',
    config: {
      type: 'modal',
      width: 500,
      blur: true,
      closeable: true
    },
    props: {
      message: 'Hello from VueModaller!'
    }
  })
  console.log('Modal result:', result)
}
</script>

<template>
  <button @click="openStandardModal">
    Open Modal
  </button>
</template>

🎭 Modal Types

Standard Modal

Perfect for confirmations, forms, and general content display.

const result = await useModal(Component, {
  config: {
    type: 'modal',
    width: 500,
    height: 400,
    blur: true,
    corner: '12px'
  }
})

Side Panel

Great for navigation menus, filters, and side content.

const result = await useModal(Component, {
  config: {
    type: 'side',
    blur: true,
    margin: 20 // Top margin
  }
})

Panel Modal

Bottom-aligned panels with rounded corners, perfect for mobile interfaces.

const result = await useModal(Component, {
  config: {
    type: 'panel',
    height: '60vh',
    corner: '16px'
  }
})

Draggable Modal (Instagram-style)

Interactive bottom sheets with smooth drag gestures.

const result = await useModal(Component, {
  config: {
    type: 'draggable',
    draggableConfig: {
      initialPosition: 'half', // 'full' | 'half'
      hideHandle: false,
      shadow: '0 -8px 24px rgba(0,0,0,0.15)',
      handle: {
        color: '#e0e0e0',
        hoverColor: '#bdbdbd',
        activeColor: '#9e9e9e',
        width: '48px',
        height: '4px',
        radius: '2px'
      }
    }
  }
})

📱 Responsive Modals

Automatically adapt modal types based on device:

const result = await useModal(Component, {
  config: {
    type: 'modal',        // Desktop type
    mobileType: 'draggable', // Mobile type
    width: 600,
    draggableConfig: {
      initialPosition: 'half'
    }
  }
})

When viewed on mobile, this will show a draggable modal instead of a standard modal!

⚙️ Configuration API

ModalConfig Interface

interface ModalConfig {
  // Modal type
  type?: 'modal' | 'side' | 'panel' | 'draggable'
  mobileType?: 'modal' | 'side' | 'panel' | 'draggable'
  
  // Dimensions
  width?: number
  height?: number | string
  
  // Appearance
  blur?: boolean           // Backdrop blur effect
  closeable?: boolean      // Allow closing by clicking outside
  corner?: string          // Border radius
  margin?: number          // Top margin (side panels)
  padding?: string         // Internal padding
  background?: string      // Background color class
  
  // Animation
  anim?: boolean          // Enable/disable animations
  
  // Draggable specific
  draggableConfig?: DraggableConfig
  
  // Lifecycle
  onClosed?: () => void   // Callback when modal closes
}

DraggableConfig Interface

interface DraggableConfig {
  initialPosition?: 'full' | 'half'
  hideHandle?: boolean
  shadow?: string
  handle?: {
    color?: string
    hoverColor?: string  
    activeColor?: string
    height?: string
    width?: string
    radius?: string | number
    marginTop?: string | number
    marginBottom?: string | number
  }
}

🎨 Styling & Theming

VueModaller uses CSS custom properties for easy theming:

:root {
  /* Backdrop */
  --modal-backdrop: rgba(0, 0, 0, 0.2);
  
  /* Modal */
  --white: #ffffff;
  --modal-border-radius: 0.75rem;
  --modal-padding: 1rem;
  --modal-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  --modal-z-index: 9999;
  
  /* Draggable Handle */
  --modal-draggable-handle-color: #ccc;
  --modal-draggable-handle-hover-color: #999;
  --modal-draggable-handle-active-color: #666;
  --modal-draggable-handle-height: 5px;
  --modal-draggable-handle-width: 45px;
  --modal-draggable-handle-radius: 4px;
}

Custom Themes

/* Dark theme example */
:root {
  --white: #1a1a1a;
  --modal-backdrop: rgba(0, 0, 0, 0.8);
  --modal-draggable-handle-color: #444;
  --modal-draggable-handle-hover-color: #666;
}

🔧 Advanced Usage

Dynamic Slot Content

const result = await useModal(Component, {
  config: { type: 'modal' },
  slots: {
    header: {
      component: MyHeaderComponent,
      props: { title: 'Custom Header' }
    },
    footer: {
      component: MyFooterComponent,
      props: { showActions: true }
    }
  }
})

Multiple Modals

// Stack multiple modals
const modal1 = useModal(Component1, { config: { type: 'modal' } })
const modal2 = useModal(Component2, { config: { type: 'side' } })

// Close all modals
import { closeAllModal } from 'vue-modaller'
closeAllModal()

Modal Results

// In your modal component
<script setup>
const emit = defineEmits(['close'])

const handleSubmit = () => {
  emit('close', { success: true, data: formData })
}

const handleCancel = () => {
  emit('close', { success: false })
}
</script>

// Usage
const result = await useModal(MyForm, { config: { type: 'modal' } })
if (result.success) {
  console.log('Form data:', result.data)
}

📱 Device Detection

VueModaller includes a powerful device detection composable:

import { useDeviceDetection } from 'vue-modaller'

export default {
  setup() {
    const { isMobile, isTablet, isDesktop, detectDevice } = useDeviceDetection()
    
    return {
      isMobile,
      isTablet, 
      isDesktop
    }
  }
}

🎯 Best Practices

Mobile-First Design

// Recommended pattern for responsive modals
const openModal = async () => {
  await useModal(Component, {
    config: {
      type: 'modal',
      mobileType: 'draggable', // Better UX on mobile
      width: 600,
      draggableConfig: {
        initialPosition: 'half'
      }
    }
  })
}

Performance Optimization

// Use markRaw for large components
import { markRaw } from 'vue'
const HeavyComponent = markRaw(MyHeavyComponent)

await useModal(HeavyComponent, {
  config: { type: 'modal' }
})

🔍 Examples

Check out our live examples to see VueModaller in action!

📄 API Reference

Functions

useModal(component, options)

Opens a modal and returns a promise.

Parameters:

  • component - Vue component to render
  • options - Configuration object

Returns: Promise<any> - Resolves with modal result

closeModal(data, index)

Programmatically close a specific modal.

closeAllModal(data)

Close all open modals.

Components

<ModalRoot />

Global modal container. Must be included in your app.

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

📝 License

MIT © Classydev

🙋‍♂️ Support


Side Panel

const result = await useModal(Component, {
  config: {
    type: 'side',
    blur: true,
    closeable: true
  }
})

Draggable Modal (Instagram-style)

const result = await useModal(Component, {
  config: {
    type: 'draggable',
    blur: true,
    closeable: true,
    draggableConfig: {
      initialPosition: 'half', // 'full' | 'half'
      handle: {
        color: '#ddd',
        hoverColor: '#bbb',
        activeColor: '#999'
      }
    }
  }
})

Configuration Options

interface ModalConfig {
  type?: 'modal' | 'side' | 'panel' | 'draggable'
  width?: number
  height?: number | string
  blur?: boolean
  closeable?: boolean
  corner?: string
  margin?: number
  padding?: number
  background?: string
  anim?: boolean
  draggableConfig?: {
    initialPosition?: 'full' | 'half'
    hideHandle?: boolean
    handle?: {
      color?: string
      hoverColor?: string
      activeColor?: string
      height?: string
      width?: string
      radius?: string
      marginTop?: string
      marginBottom?: string
    }
  }
}

API

useModal(component, options)

Opens a modal and returns a promise that resolves with the modal result.

Parameters:

  • component: Vue component to render in the modal
  • options: Modal configuration object

Returns: Promise<any> - Resolves when modal is closed

ModalRoot

Global component that manages modal rendering. Must be added to your app template.

Styling

VueModaller uses CSS variables for easy customization:

:root {
  --modal-backdrop-color: rgba(0, 0, 0, 0.5);
  --modal-background-color: #ffffff;
  --modal-border-radius: 0.75rem;
  --modal-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
  --modal-draggable-handle-color: #ddd;
  /* ... more variables */
}

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.